Apache Camel 개발 가이드

Red Hat Fuse 7.9

Apache Camel로 애플리케이션 개발

Red Hat Fuse Documentation Team

초록

이 가이드에서는 Apache Camel을 사용하여 JBoss Fuse 애플리케이션을 개발하는 방법을 설명합니다. 기본 구성 요소, 엔터프라이즈 통합 패턴, 라우팅 표현식 및 서술자 언어의 기본 구문, Apache CXF 구성 요소로 웹 서비스를 생성하고 Apache Camel API를 사용하여 웹 서비스를 생성하는 방법과 Java API를 래핑하는 Camel 구성 요소를 생성하는 방법을 설명합니다.

보다 포괄적 수용을 위한 오픈 소스 용어 교체

Red Hat은 코드, 문서, 웹 속성에서 문제가 있는 용어를 교체하기 위해 최선을 다하고 있습니다. 먼저 마스터(master), 슬레이브(slave), 블랙리스트(blacklist), 화이트리스트(whitelist) 등 네 가지 용어를 교체하고 있습니다. 이러한 변경 작업은 작업 범위가 크므로 향후 여러 릴리스에 걸쳐 점차 구현할 예정입니다. 자세한 내용은 CTO Chris Wright의 메시지에서 참조하십시오.

I 부. 엔터프라이즈 통합 패턴 구현

이 부분에서는 Apache Camel을 사용하여 경로를 빌드하는 방법을 설명합니다. 기본 빌딩 블록 및 EIP 구성 요소를 다룹니다.

1장. 경로 정의용 블록 빌드

초록

Apache Camel은 경로를 정의하는 데 필요한 두 가지 대체 DSL( Domain Specific Languages )을 지원합니다(Java DSL 및 Spring XML DSL). 경로를 정의하는 기본 빌딩 블록은 끝점프로세서이며, 프로세서 의 동작은 일반적으로 표현식 또는 논리 서술자 에 의해 수정됩니다. Apache Camel을 사용하면 다양한 언어를 사용하여 표현식 및 서술자를 정의할 수 있습니다.

1.1. RouteBuilder 클래스 구현

1.1.1. 개요

DSL( Domain Specific Language )을 사용하려면 RouteBuilder 클래스를 확장하고 라우팅 규칙을 정의하는 configure() 메서드를 재정의합니다.

필요한 만큼 RouteBuilder 클래스를 정의할 수 있습니다. 각 클래스는 한 번 인스턴스화되며 CamelContext 오브젝트에 등록됩니다. 일반적으로 각 RouteBuilder 오브젝트의 라이프사이클은 라우터를 배포하는 컨테이너에서 자동으로 관리합니다.

1.1.2. RouteBuilder 클래스

라우터 개발자로서 핵심 작업은 RouteBuilder 클래스를 하나 이상 구현하는 것입니다. 다음 두 가지 대체 RouteBuilder 클래스가 있습니다.

  • org.apache.camel.builder.RouteBuilder Cryostat-ECDHE This is the generic RouteBuilder base class that is suitable for deploying into any container type. camel-core 아티팩트로 제공됩니다.
  • org.apache.camel.spring.SpringRouteBuilder Cryostat 이 기본 클래스는 Spring 컨테이너에 특별히 조정됩니다. 특히 다음의 Spring 특정 기능에 대한 추가 지원을 제공합니다. Spring 레지스트리에서 빈을 조회합니다(JustRef() Java DSL 명령 사용) 및 트랜잭션(자세한 내용은 트랜잭션 가이드 참조). 이는 camel-spring 아티팩트로 제공됩니다.

RouteBuilder 클래스는 라우팅 규칙을 시작하는 데 사용되는 메서드를 정의합니다(예: from(), intercept(), exception()).

1.1.3. RouteBuilder 구현

예 1.1. “RouteBuilder 클래스 구현” 최소 RouteBuilder 구현을 표시합니다. configure() 메서드 본문에는 라우팅 규칙이 포함되어 있으며 각 규칙은 단일 Java 문입니다.

예 1.1. RouteBuilder 클래스 구현

import org.apache.camel.builder.RouteBuilder;

public class MyRouteBuilder extends RouteBuilder {

public void configure() {
  // Define routing rules here:
  from("file:src/data?noop=true").to("file:target/messages");

  // More rules can be included, in you like.
  // ...
}
}

의 규칙 형식 (URL1).to(URL2) 은 디렉토리 src/data 에서 파일을 읽고 디렉터리 target/messages 디렉터리에 전송하도록 라우터에 지시합니다. 옵션 ?noop=true 는 라우터가 src/data 디렉토리에 있는 소스 파일을 유지(삭제하지 않음)하도록 지시합니다.

참고

contextScan 을 Spring 또는 블루프린트와 함께 사용하여 RouteBuilder 클래스를 필터링하면 기본적으로 Apache Camel에서 Singleton 빈을 찾습니다. 그러나 이전 동작을 켜서 새 옵션 includeNonSingletons 로 범위가 지정된 프로토타입을 포함할 수 있습니다.

1.2. 기본 Java DSL 구문

1.2.1. DSL이란 무엇입니까?

DSL(Domain Specific Language)은 특수한 목적을 위해 설계된 최소 언어입니다. DSL은 논리적으로 완료할 필요는 없지만 선택한 도메인에서 문제를 적절하게 설명하기 위해 표현 가능한 권한이 필요합니다. 일반적으로 DSL에는 전용 구문 분석기, 인터프리터 또는 컴파일러가 필요하지 않습니다. DSL은 기존 객체 지향 호스트 언어의 상단에 파키백을 할 수 있으며 호스트 언어 API의 구성에 DSL 구문이 깔끔하게 맵을 제공했습니다.

가상 DSL에서 다음과 같은 명령 시퀀스를 고려하십시오.

command01;
command02;
command03;

다음과 같이 이러한 명령을 Java 메서드 호출에 매핑할 수 있습니다.

command01().command02().command03()

블록을 Java 메서드 호출에 매핑할 수도 있습니다. 예를 들면 다음과 같습니다.

command01().startBlock().command02().command03().endBlock()

DSL 구문은 호스트 언어 API의 데이터 유형에 의해 암시적으로 정의됩니다. 예를 들어 Java 메서드의 반환 유형은 다음에 합법적으로 호출할 수 있는 방법을 결정합니다( DSL의 다음 명령과 동일함).

1.2.2. 라우터 규칙 구문

Apache Camel은 라우팅 규칙을 정의하는 라우터 DSL 을 정의합니다. 이 DSL을 사용하여 RouteBuilder.configure() 구현의 본문에 규칙을 정의할 수 있습니다. 그림 1.1. “로컬 라우팅 규칙” 는 로컬 라우팅 규칙을 정의하는 기본 구문의 개요를 보여줍니다.

그림 1.1. 로컬 라우팅 규칙

로컬 라우팅 규칙

로컬 규칙은 항상 라우팅 규칙의 메시지 소스(소비자 끝점)를 지정하는 from("EndpointURL") 메서드로 시작합니다. 그런 다음 임의로 긴 프로세서 체인을 규칙에 추가할 수 있습니다(예: filter()). 일반적으로 규칙을 통과하는 메시지의 대상(프로덕터끝점)을 지정하는 to("EndpointURL") 메서드로 규칙을 종료합니다. 그러나 to() 로 규칙을 종료할 필요는 없습니다. 규칙에서 메시지 대상을 지정하는 다른 방법이 있습니다.

참고

특수 프로세서 유형(예: intercept(), exception() 또는 errorHandler())으로 규칙을 시작하여 글로벌 라우팅 규칙을 정의할 수도 있습니다. 글로벌 규칙은 이 가이드의 범위를 벗어납니다.

1.2.3. 소비자 및 생산자

로컬 규칙은 항상 from("EndpointURL") 을 사용하여 소비자 끝점을 정의하여 시작하고 일반적으로 (항상은 아님) to("EndpointURL") 를 사용하여 생산자 엔드포인트를 정의하여 끝납니다. 엔드포인트 URL인 EndpointURL 은 배포 시 구성된 구성 요소 중 하나를 사용할 수 있습니다. 예를 들어 파일 엔드포인트, file:MyMessageDirectory, Apache CXF 엔드포인트, cxf:MyServiceName 또는 Apache ActiveMQ 엔드포인트 activemq:queue:MyQName 을 사용할 수 있습니다. 구성 요소 유형의 전체 목록은 Apache Camel 구성 요소 참조를 참조하십시오.

1.2.4. 교환

교환 오브젝트는 메타데이터에 의해 보강된 메시지로 구성됩니다. 교환은 라우팅 규칙을 통해 메시지가 전파되는 표준 형식이므로 Apache Camel에서 교환은 매우 중요합니다. 교환의 주요 구성 요소는 다음과 같습니다.

  • message Cryostat- Cryostat는 교환에 의해 캡슐화된 현재 메시지입니다. 경로를 통해 교환이 진행됨에 따라 이 메시지가 수정될 수 있습니다. 따라서 경로 시작 시 In 메시지는 일반적으로 경로 끝에 있는 In 메시지와 동일하지 않습니다. org.apache.camel.Message 유형은 다음 부분과 함께 메시지의 일반 모델을 제공합니다.

    • 본문.
    • headers.
    • 첨부 파일.

    이것이 메시지의 일반적인 모델임을 인식하는 것이 중요합니다. Apache Camel은 다양한 프로토콜 및 엔드포인트 유형을 지원합니다. 따라서 메시지 본문 또는 메시지 헤더의 형식을 표준화할 수 없습니다. 예를 들어 JMS 메시지의 본문은 HTTP 메시지 또는 웹 서비스 메시지의 본문과 완전히 다른 형식을 갖습니다. 이러한 이유로 본문과 헤더는 Object 유형으로 선언됩니다. 그런 다음 본문과 헤더의 원래 내용은 교환 인스턴스를 만든 엔드포인트(즉, from() 명령에 나타나는 끝점)에 의해 결정됩니다.

  • Explicit - message는 응답 메시지 또는 변환된 메시지의 임시 유지 영역입니다. 특정 처리 노드(특히 to() 명령)는 In 메시지를 요청으로 처리하고 생산자 엔드포인트로 보낸 다음 해당 끝점에서 응답을 수신하여 현재 메시지를 수정할 수 있습니다. 그런 다음 응답 메시지가 교환의 Out 메시지 슬롯에 삽입됩니다.

    일반적으로 Out 메시지가 현재 노드에서 설정된 경우 Apache Camel은 경로의 다음 노드에 전달할 때 다음과 같이 교환을 수정합니다. 이전 In 메시지는 삭제되고 Out 메시지는 In 메시지 슬롯으로 이동합니다. 따라서 응답은 새 현재 메시지가 됩니다. Apache Camel이 노드를 경로에서 함께 연결하는 방법에 대한 자세한 내용은 2.1절. “파이프라인 처리” 을 참조하십시오.

    그러나 외부 메시지가 다르게 처리되는 특별한 경우가 있습니다. 경로 시작 시 소비자 끝점에 응답 메시지가 예상되는 경우 경로의 맨 끝에 있는 Out 메시지가 소비자 끝점의 응답 메시지(및 더 많은 경우 최종 노드가 아웃 메시지 또는 소비자 끝점이 중단됨)로 이동합니다.

  • message exchange pattern (MEP) Cryostat-propertyffects the interaction between the exchange and endpoints in the route, as follows:

    • 원래 교환을 생성하는 소비자 끝점은 MEP의 초기 값을 설정합니다. 초기 값은 소비자 끝점이 응답을 수신할지(예: InOut MEP)를 수신할지 여부를 나타냅니다(예: InOnly MEP).
    • 생산자 엔드포인트 (MEP)는 경로를 따라 교환이 발생하는 생산자 끝점에 영향을 미칩니다(예: 교환이 to() 노드를 통과하는 경우). 예를 들어 현재 MEP가 InOnly 이면 to() 노드는 끝점에서 응답을 수신할 것으로 예상하지 않습니다. 때때로 교환의 생산자 엔드 포인트와의 상호 작용을 사용자 정의하기 위해 현재 MEP를 변경해야하는 경우가 있습니다. 자세한 내용은 1.4절. “끝점” 에서 참조하십시오.
  • 현재 메시지에 대한 메타데이터를 포함하는 이름이 지정된 속성의 목록 exchange properties that contains metadata for the current message

1.2.5. 메시지 교환 패턴

Exchange 개체를 사용하면 다양한 메시지 교환 패턴에 대한 메시지 처리를 쉽게 일반화할 수 있습니다. 예를 들어 비동기 프로토콜은 소비자 끝점에서 생산자 엔드포인트( InOnly MEP)로 이동하는 단일 메시지로 구성된 MEP를 정의할 수 있습니다. 반면 RPC 프로토콜은 요청 메시지와 응답 메시지( InOut MEP)로 구성된 MEP를 정의할 수 있습니다. 현재 Apache Camel은 다음 MEP를 지원합니다.

  • InOnly
  • RobustInOnly
  • InOut
  • InOptionalOut
  • OutOnly
  • RobustOutOnly
  • OutIn
  • OutOptionalIn

여기서 이러한 메시지 교환 패턴은 열거 유형인 org.apache.camel.ExchangePattern 의 상수로 표시됩니다.

1.2.6. 그룹화된 교환

경우에 따라 여러 교환 인스턴스를 캡슐화하는 단일 교환을 사용하는 것이 유용합니다. 이를 위해 그룹화된 교환을 사용할 수 있습니다. 그룹화된 교환은 기본적으로 Exchange.GROUPED_EXCHANGE 교환 속성에 저장된 java.util.List of Exchange 개체를 포함하는 교환 인스턴스입니다. 그룹화된 교환을 사용하는 방법에 대한 예제는 8.5절. “수집기” 를 참조하십시오.

1.2.7. 프로세서

프로세서는 경로를 통과하는 교환 스트림에 액세스하고 수정할 수 있는 경로의 노드입니다. 프로세서에서는 동작을 수정하는 표현식 또는 서술자 인수를 사용할 수 있습니다. 예를 들어 그림 1.1. “로컬 라우팅 규칙” 에 표시된 규칙에는 xpath() 서술자를 인수로 사용하는 filter() 프로세서가 포함되어 있습니다.

1.2.8. 표현식 및 서술자

식(문자열 또는 기타 데이터 형식에 평가) 및 서술자(true 또는 false로 평가)는 기본 제공 프로세서 유형에 대한 인수로 자주 발생합니다. 예를 들어 다음 필터 규칙은 foo 헤더가 값 표시줄 과 동일한 경우에만 메시지에서 전파됩니다.

from("seda:a").filter(header("foo").isEqualTo("bar")).to("seda:b");

여기서 필터가 서술자인 header("foo").isEqualTo("bar") 에 의해 검증됩니다. 메시지 콘텐츠를 기반으로 보다 정교한 서술자 및 표현식을 구성하려면 표현식 및 서술자 언어 중 하나를 사용할 수 있습니다( II 부. 라우팅 표현식 및 서술자 언어참조).

1.3. Spring XML 파일의 라우터 스키마

1.3.1. 네임스페이스

다음 XML 스키마의 namespace에 XML DSL between- Cryostatbelongs를 정의하는 라우터 스키마 Cryostat- Cryostat:

http://camel.apache.org/schema/spring

1.3.2. 스키마 위치 지정

라우터 스키마의 위치는 일반적으로 Apache 웹 사이트의 최신 버전의 스키마를 참조하는 http://camel.apache.org/schema/spring/camel-spring.xsd 로 지정됩니다. 예를 들어 Apache Camel Spring 파일의 루트 요소는 일반적으로 예 1.2. “라우터 스키마 위치 지정” 에 표시된 대로 구성됩니다.

예 1.2. 라우터 스키마 위치 지정

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:camel="http://camel.apache.org/schema/spring"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
       http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">

  <camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
    <!-- Define your routing rules here -->
  </camelContext>
</beans>

1.3.3. 런타임 스키마 위치

런타임에 Apache Camel은 Spring 파일에 지정된 스키마 위치에서 라우터 스키마를 다운로드하지 않습니다. 대신 Apache Camel은 camel-spring JAR 파일의 루트 디렉토리에서 스키마 사본을 자동으로 선택합니다. 이렇게 하면 Spring 파일을 구문 분석하는 데 사용되는 스키마의 버전이 항상 현재 런타임 버전과 일치합니다. Apache 웹 사이트에 게시된 최신 버전의 스키마가 현재 사용 중인 런타임 버전과 일치하지 않을 수 있으므로 이는 중요합니다.

1.3.4. XML 편집기 사용

일반적으로 전체 기능을 갖춘 XML 편집기를 사용하여 Spring 파일을 편집하는 것이 좋습니다. XML 편집기의 자동 완성 기능을 사용하면 라우터 스키마를 준수하는 XML을 더 쉽게 작성할 수 있으며 XML이 잘못 구성된 경우 편집기는 즉시 경고할 수 있습니다.

XML 편집기는 일반적으로 xsi:schemaLocation 특성에 지정하는 위치에서 스키마를 다운로드하는 데 의존합니다. 편집하는 동안 올바른 스키마 버전을 사용하고 있는지 확인하려면 일반적으로 camel-spring.xsd 파일의 특정 버전을 선택하는 것이 좋습니다. 예를 들어 Apache Camel의 2.3 버전에 대한 Spring 파일을 편집하려면 다음과 같이 beans 요소를 수정할 수 있습니다.

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:camel="http://camel.apache.org/schema/spring"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
       http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring-2.3.0.xsd">
...

편집을 완료하면 기본 camel-spring.xsd 로 다시 변경합니다. 현재 다운로드할 수 있는 스키마 버전을 확인하려면 웹 페이지인 http://camel.apache.org/schema/spring 로 이동합니다.

1.4. 끝점

1.4.1. 개요

Apache Camel 끝점은 경로에 있는 메시지의 소스 및 싱크입니다. 끝점은 매우 일반적인 종류의 빌딩 블록입니다. 충족해야 하는 유일한 요구 사항은 메시지 소스(프로덕션 끝점) 또는 메시지 싱크(컨트리스팅)로 작동한다는 것입니다. 따라서 HTTP와 같은 프로토콜 지원 끝점에서 정기적으로 더미 메시지를 생성하는 Quartz와 같은 간단한 타이머 끝점에 이르기까지 Apache Camel에서 지원되는 다양한 끝점 유형이 있습니다. Apache Camel의 주요 강점 중 하나는 새 엔드포인트 유형을 구현하는 사용자 지정 구성 요소를 비교적 쉽게 추가할 수 있다는 것입니다.

1.4.2. 엔드포인트 URI

끝점은 다음과 같은 일반적인 형식을 갖는 끝점 URI 로 식별됩니다.

scheme:contextPath[?queryOptions]

URI 스키마http 와 같은 프로토콜을 식별하고 contextPath 는 프로토콜에서 해석되는 URI 세부 정보를 제공합니다. 또한 대부분의 스키마를 사용하면 다음 형식으로 지정된 쿼리 옵션인 queryOptions 를 정의할 수 있습니다.

?option01=value01&option02=value02&...

예를 들어 다음 HTTP URI를 사용하여 Google 검색 엔진 페이지에 연결할 수 있습니다.

http://www.google.com

다음 File URI를 사용하여 C:\temp\src\data 디렉터리에 나타나는 모든 파일을 읽을 수 있습니다.

file://C:/temp/src/data

모든 스키마 가 프로토콜을 나타내는 것은 아닙니다. 경우에 따라 스키마 는 타이머와 같은 유용한 유틸리티에 대한 액세스를 제공합니다. 예를 들어 다음 Timer 엔드포인트 URI는 1초마다 교환을 생성합니다(=1000밀리초). 이를 사용하여 경로의 활동을 예약할 수 있습니다.

timer://tickTock?period=1000

1.4.3. 장기 엔드 포인트 URI 작업

경우에 따라 끝점 URI가 제공된 모든 관련 구성 정보로 인해 상당히 길어질 수 있습니다. JBoss Fuse 6.2 이상에서는 긴 URI 작업을 보다 쉽게 관리할 수 있도록 두 가지 접근 방식을 사용할 수 있습니다.

Endpoints 9월 구성

끝점을 별도로 구성할 수 있으며 경로에서 단축 ID를 사용하여 끝점을 참조합니다.

<camelContext ...>

  <endpoint id="foo" uri="ftp://foo@myserver">
    <property name="password" value="secret"/>
    <property name="recursive" value="true"/>
    <property name="ftpClient.dataTimeout" value="30000"/>
    <property name="ftpClient.serverLanguageCode" value="fr"/>
  </endpoint>

  <route>
    <from uri="ref:foo"/>
    ...
  </route>
</camelContext>

URI에서 일부 옵션을 구성한 다음 속성 속성을 사용하여 추가 옵션을 지정하거나 URI의 옵션을 재정의할 수도 있습니다.

<endpoint id="foo" uri="ftp://foo@myserver?recursive=true">
  <property name="password" value="secret"/>
  <property name="ftpClient.dataTimeout" value="30000"/>
  <property name="ftpClient.serverLanguageCode" value="fr"/>
</endpoint>
새 라인을 통해 엔드 포인트 구성 분할

새 행을 사용하여 URI 속성을 분할할 수 있습니다.

<route>
  <from uri="ftp://foo@myserver?password=secret&amp;
           recursive=true&amp;ftpClient.dataTimeout=30000&amp;
           ftpClientConfig.serverLanguageCode=fr"/>
  <to uri="bean:doSomething"/>
</route>
참고

각 줄에서 하나 이상의 옵션을 지정하고 각각 & 로 구분하여 지정할 수 있습니다.

1.4.4. URI에 시간 지정

Apache Camel 구성 요소의 많은에는 일정 기간(예: 시간 초과 값을 지정하는 등) 값이 있는 옵션이 있습니다. 기본적으로 이러한 기간 옵션은 일반적으로 밀리 초의 기간으로 해석되는 순수수로 지정됩니다. 그러나 Apache Camel은 기간 동안 더 읽기 쉬운 구문을 지원하므로 시간, 분, 초 단위로 기간을 표시할 수 있습니다. 공식적으로 사람이 읽을 수 있는 기간은 다음 구문을 따르는 문자열입니다.

[NHour(h|hour)][NMin(m|minute)][NSec(s|second)]

대괄호 안에 있는 각 용어( [] )는 선택 사항이며 표기법 (A|B)AB 가 대안임을 나타냅니다.

예를 들어 다음과 같이 45 분 기간을 사용하여 타이머 끝점을 구성할 수 있습니다.

from("timer:foo?period=45m")
  .to("log:foo");

다음과 같이 시간, 분 및 두 번째 단위의 임의의 조합을 사용할 수도 있습니다.

from("timer:foo?period=1h15m")
  .to("log:foo");
from("timer:bar?period=2h30s")
  .to("log:bar");
from("timer:bar?period=3h45m58s")
  .to("log:bar");

1.4.5. URI 옵션에 원시 값 지정

기본적으로 URI에 지정하는 옵션 값은 자동으로 URI로 인코딩됩니다. 경우에 따라 이는 바람직하지 않은 동작입니다. 예를 들어 암호 옵션을 설정할 때 URI 인코딩 없이 원시 문자 문자열을 전송하는 것이 좋습니다.

구문, RAW(RawValue) 로 옵션 값을 지정하여 URI 인코딩을 전환할 수 있습니다. 예를 들면 다음과 같습니다.

from("SourceURI")
 .to("ftp:joe@myftpserver.com?password=RAW(se+re?t&23)&binary=true")

이 예에서 password 값은 리터럴 값 se+re?t&23 으로 전송됩니다.

1.4.6. 대소문자를 구분하지 않는 enum 옵션

일부 끝점 URI 옵션은 Java 열거 상수에 매핑됩니다. 예를 들어 로그 구성 요소의 수준 옵션은 enum 값, INFO,WARN,ERROR 등을 사용할 수 있습니다. 이 유형 변환은 대소문자를 구분하지 않으므로 다음 대안을 사용하여 로그 생산자 끝점의 로깅 수준을 설정할 수 있습니다.

<to uri="log:foo?level=info"/>
<to uri="log:foo?level=INfo"/>
<to uri="log:foo?level=InFo"/>

1.4.7. URI 리소스 지정

Camel 2.17에서 XSLT와 같은 리소스 기반 구성 요소는 ref: 를 접두사로 사용하여 레지스트리에서 리소스 파일을 로드할 수 있습니다.

예를 들어 ifmyvelocityscriptbeanmysimplescriptbean 은 레지스트리에 있는 두 빈 ID입니다.

Velocity endpoint:
------------------
from("velocity:ref:myvelocityscriptbean").<rest_of_route>.

Language endpoint (for invoking a scripting language):
-----------------------------------------------------
from("direct:start")
  .to("language:simple:ref:mysimplescriptbean")
 Where Camel implicitly converts the bean to a String.

1.4.8. Apache Camel 구성 요소

각 URI 스키마Apache Camel 구성 요소가 기본적으로 엔드포인트 팩토리인 Apache Camel 구성 요소에 매핑됩니다. 즉, 특정 유형의 엔드포인트를 사용하려면 런타임 컨테이너에 해당 Apache Camel 구성 요소를 배포해야 합니다. 예를 들어 JMS 엔드포인트를 사용하려면 컨테이너에 JMS 구성 요소를 배포합니다.

Apache Camel은 다양한 전송 프로토콜 및 타사 제품과 애플리케이션을 통합할 수 있는 다양한 구성 요소를 제공합니다. 예를 들어 일반적으로 사용되는 구성 요소 중 일부는 File, JMS, CXF (Web services), HTTP,kafkaty, Direct 및 Mock입니다. 지원되는 구성 요소의 전체 목록은 Apache Camel 구성 요소 설명서 를 참조하십시오.

대부분의 Apache Camel 구성 요소는 Camel 코어에 별도로 패키지됩니다. Maven을 사용하여 애플리케이션을 빌드하는 경우 관련 구성 요소 아티팩트에 대한 종속성을 추가하여 쉽게 애플리케이션에 구성 요소(및 타사 종속 항목)를 추가할 수 있습니다. 예를 들어 HTTP 구성 요소를 포함하려면 다음 Maven 종속성을 프로젝트 POM 파일에 추가합니다.

<!-- Maven POM File -->
  <properties>
    <camel-version>{camelFullVersion}</camel-version>
    ...
  </properties>

  <dependencies>
    ...
    <dependency>
      <groupId>org.apache.camel</groupId>
      <artifactId>camel-http</artifactId>
      <version>${camel-version}</version>
    </dependency>
    ...
  </dependencies>

다음 구성 요소는 Camel 코어( camel-core 아티팩트에서)에 기본 제공되므로 항상 사용할 수 있습니다.

  • Cryostat
  • 검색
  • 데이터 세트
  • 직접
  • 파일
  • log
  • mock
  • 속성
  • Ref
  • SEDA
  • 타이머
  • VM

1.4.9. 소비자 끝점

소비자 끝점 은 경로 시작 시 표시되는 끝점입니다(즉, from() DSL 명령에서). 즉, 소비자 끝점은 경로에서 처리를 시작합니다. 이는 새로운 교환 인스턴스(일반적으로 수신 또는 획득한 일부 메시지에 따라)를 생성하고 나머지 경로에서 교환을 처리하는 스레드를 제공합니다.

예를 들어 다음 JMS 소비자 끝점은 결제 대기열에서 메시지를 가져와서 경로에서 처리합니다.

from("jms:queue:payments")
  .process(SomeProcessor)
  .to("TargetURI");

또는 이와 동등한 경우 Spring XML:

<camelContext id="CamelContextID"
              xmlns="http://camel.apache.org/schema/spring">
  <route>
    <from uri="jms:queue:payments"/>
    <process ref="someProcessorId"/>
    <to uri="TargetURI"/>
  </route>
</camelContext>

일부 구성 요소는 소비자만 사용할 수 있습니다. 즉, 소비자 끝점을 정의하는 데만 사용할 수 있습니다. 예를 들어 Quartz 구성 요소는 소비자 끝점을 정의하는 데 독점적으로 사용됩니다. 다음 Quartz 엔드포인트는 1초마다 (1000밀리초) 이벤트를 생성합니다.

from("quartz://secondTimer?trigger.repeatInterval=1000")
  .process(SomeProcessor)
  .to("TargetURI");

원하는 경우 fromF() Java DSL 명령을 사용하여 엔드포인트 URI를 포맷된 문자열로 지정할 수 있습니다. 예를 들어 사용자 이름과 암호를 FTP 끝점의 URI로 대체하려면 다음과 같이 Java에 경로를 작성할 수 있습니다.

fromF("ftp:%s@fusesource.com?password=%s", username, password)
  .process(SomeProcessor)
  .to("TargetURI");

여기서 첫 번째 발생 %susername 문자열의 값으로 교체되고 두 번째 발생 %spassword 문자열로 교체됩니다. 이 문자열 형식 지정 메커니즘은 String.format() 에 의해 구현되며 C Cryostat () 함수에서 제공하는 포맷과 유사합니다. 자세한 내용은 java.util.Formatter 를 참조하십시오.

1.4.10. 생산자 끝점

생산자 엔드포인트 는 경로의 중간 또는 끝에 표시되는 엔드포인트입니다(예: to() DSL 명령). 즉, 생산자 끝점은 기존 교환 오브젝트를 수신하고 교환 내용을 지정된 엔드포인트로 보냅니다.

예를 들어 다음 JMS 생산자 끝점은 현재 교환의 내용을 지정된 JMS 큐로 푸시합니다.

from("SourceURI")
  .process(SomeProcessor)
  .to("jms:queue:orderForms");

Spring XML과 동일합니다.

<camelContext id="CamelContextID" xmlns="http://camel.apache.org/schema/spring">
  <route>
    <from uri="SourceURI"/>
    <process ref="someProcessorId"/>
    <to uri="jms:queue:orderForms"/>
  </route>
</camelContext>

일부 구성 요소는 생산자만, 즉 생산자 끝점을 정의하는 데만 사용할 수 있습니다. 예를 들어 HTTP 끝점은 생산자 엔드포인트를 정의하는 데만 사용됩니다.

from("SourceURI")
  .process(SomeProcessor)
  .to("http://www.google.com/search?hl=en&q=camel+router");

원하는 경우 toF() Java DSL 명령을 사용하여 엔드포인트 URI를 포맷된 문자열로 지정할 수 있습니다. 예를 들어 사용자 지정 Google 쿼리를 HTTP URI로 대체하려면 다음과 같이 Java에서 경로를 작성할 수 있습니다.

from("SourceURI")
  .process(SomeProcessor)
  .toF("http://www.google.com/search?hl=en&q=%s", myGoogleQuery);

여기서 %s 발생은 사용자 지정 쿼리 문자열인 myGoogleQuery 로 교체됩니다. 자세한 내용은 java.util.Formatter 를 참조하십시오.

1.5. 프로세서

1.5.1. 개요

라우터에서 단순히 소비자 엔드포인트를 생산자 엔드포인트에 연결하는 것보다 더 흥미로운 작업을 수행할 수 있도록 경로에 프로세서를 추가할 수 있습니다. 프로세서는 라우팅 규칙에 삽입하여 규칙을 통과하는 메시지를 임의의 처리를 수행할 수 있는 명령입니다. Apache Camel은 표 1.1. “Apache Camel 프로세서” 와 같이 다양한 프로세서를 제공합니다.

표 1.1. Apache Camel 프로세서

Java DSLXML DSL설명

aggregate()

aggregate

8.5절. “수집기”여러 개의 들어오는 교환을 단일 교환으로 결합하는 집계기를 생성합니다.

aop()

AOP

지정된 하위 경로 전후에 작업을 수행하려면 Aspect Oriented Programming (AOP)을 사용합니다.

bean(), beanRef()

Cryostat

Java 개체(또는 8080)에서 메서드를 호출하여 현재 교환을 처리합니다. 2.4절. “Cryostat 통합”을 참조하십시오.

choice()

선택

8.1절. “콘텐츠 기반 라우터”: 교환 컨텐츠에 따라 whenotherwise 절을 사용하여 특정 하위 경로를 선택합니다.

convertBodyTo()

convertBodyTo

메시지 본문을 지정된 형식으로 변환합니다.Converts the In message body to the specified type.

delay()

delay

8.9절. “Delayer”: 경로의 마지막 부분으로 교환의 전파를 지연합니다.

doTry()

doTry

doCatch,doFinally, end 절을 사용하여 예외 처리에 대한 try/catch 블록을 생성합니다.

end()

해당 없음

현재 명령 블록을 종료합니다.

enrich(),enrichRef()

번성

10.1절. “콘텐츠 Enricher”: 현재 교환과 지정된 생산자 엔드포인트 URI에서 요청된 데이터를 결합합니다.

filter()

filter

8.2절. “메시지 필터”: 서술자 표현식을 사용하여 들어오는 교환을 필터링합니다.

idempotentConsumer()

idempotentConsumer

11.8절. “idempotent 소비자”: 중복 메시지를 억제하는 전략을 구현합니다.

inheritErrorHandler()

@inheritErrorHandler

특정 경로 노드에서 상속된 오류 처리기를 비활성화하는 데 사용할 수 있는 부울 옵션(Java DSL에서 하위 항목으로 정의됨 및 XML DSL의 속성으로 정의됨).

inOnly()

inOnly

현재 교환의 MEP를 InOnly (패키지 없는 경우)로 설정하거나 교환을 지정된 엔드포인트에 InOnly 로 보냅니다.

inOut()

inOut

현재 교환의 MEP를 InOut (패키지 없는 경우)로 설정하거나 지정된 엔드포인트에 InOut 으로 교환을 보냅니다.

loadBalance()

loadBalance

8.10절. “로드 밸런서”끝점 컬렉션에 대한 로드 밸런싱을 구현합니다.

log()

log

콘솔에 메시지를 기록합니다.

loop()

loop

8.16절. “loop”: 각 교환을 경로의 마지막 부분으로 반복적으로 다시 보냅니다.

markRollbackOnly()

@markRollbackOnly

현재 롤백에 대한 트랜잭션만 표시합니다(예외가 발생하지 않음). XML DSL에서 이 옵션은 rollback 요소에서 부울 속성으로 설정됩니다. Apache Karaf 트랜잭션 가이드를 참조하십시오.

markRollbackOnlyLast()

@markRollbackOnlyLast

하나 이상의 트랜잭션이 이전에 이 스레드와 연결된 후 일시 중지된 경우 이 명령은 롤백에 대한 최신 트랜잭션만 표시합니다(예외 발생 없음). XML DSL에서 이 옵션은 rollback 요소에서 부울 속성으로 설정됩니다. Apache Karaf 트랜잭션 가이드를 참조하십시오.

marshal()

marshal

특정 전송 프로토콜을 통해 전송하기 위해 지정된 데이터 형식을 사용하여 하위 수준 또는 바이너리 형식으로 변환합니다.

multicast()

멀티 캐스트

8.13절. “멀티 캐스트”: 여러 대상에 대한 현재 교환을 멀티 캐스트하여 각 대상의 자체 복사본을 교환합니다.

onCompletion()

onCompletion

기본 경로가 완료된 후 실행되는 하위 경로(Java DSL에서 end() 로 종료)를 정의합니다. 2.14절. “OnCompletion” 을 참조하십시오.

onException()

onException

지정된 예외가 발생할 때마다 실행되는 하위 경로(Java DSL에서 end() 로 종료)를 정의합니다. 일반적으로 자체 행(경로에 없음)에 정의되어 있습니다.

pipeline()

pipeline

5.4절. “파이프 및 필터”하나의 끝점의 출력이 다음 끝점의 입력이 되는 일련의 끝점으로 교환을 보냅니다. 2.1절. “파이프라인 처리” 을 참조하십시오.

policy()

policy

현재 경로에 정책을 적용합니다(현재는 트랜잭션 정책에서만 사용됨- Cryostat 참조 Apache Karaf 트랜잭션 가이드 ).

pollEnrich(),pollEnrichRef()

pollEnrich

10.1절. “콘텐츠 Enricher”: 지정된 소비자 끝점 URI에서 폴링된 데이터와 현재 교환을 결합합니다.

process(),processRef

process

현재 교환에서 사용자 지정 프로세서를 실행합니다. “사용자 정의 프로세서”III 부. 고급 Camel 프로그래밍 을 참조하십시오.

recipientList()

recipientList

8.3절. “수신자 목록”: 교환을 런타임에 계산된 수신자 목록으로 보냅니다(예: 헤더 내용에 따라 다름).

removeHeader()

removeHeader

교환의 In 메시지에서 지정된 헤더를 제거합니다.

removeHeaders()

removeHeaders

교환의 In 메시지에서 지정된 패턴과 일치하는 헤더를 제거합니다. 패턴의 형식은 prefix\* Cryostat->-<in 이 경우 prefix- Cryostatotherwise로 시작하는 모든 이름과 일치하며 정규식으로 해석됩니다.

removeProperty()

removeProperty

지정된 교환 속성을 제거합니다.

removeProperties()

removeProperties

지정된 패턴과 일치하는 속성을 교환에서 제거합니다. 쉼표로 구분된 1개 이상의 문자열 목록을 인수로 사용합니다. 첫 번째 문자열은 패턴입니다(위의 removeHeaders() 참조). 후속 문자열은 예외를 지정하며 이러한 속성은 그대로 유지됩니다.Subsequent strings specify exceptions - these properties remain.

resequence()

resequence

8.6절. “Resequencer”: 지정된 비교 작업을 기반으로 들어오는 교환을 다시 주문합니다. 일괄 처리 모드 및 스트림 모드를 지원합니다.

rollback()

rollback

(기본값) 현재 트랜잭션에 대한 롤백만 표시합니다(기본적으로 예외도 발생). Apache Karaf 트랜잭션 가이드를 참조하십시오.

routingSlip()

routingSlip

8.7절. “라우팅 슬립”: 슬립 헤더에서 추출된 끝점 URI 목록을 기반으로 동적으로 구성된 파이프라인을 통해 교환을 라우팅합니다.

sample()

샘플

샘플링 throttler를 생성하여 경로의 트래픽에서 교환 샘플을 추출할 수 있습니다.

setBody()

setBody

교환의 메시지 본문을 설정합니다.

setExchangePattern()

setExchangePattern

현재 교환의 MEP를 지정된 값으로 설정합니다. “메시지 교환 패턴”을 참조하십시오.

setHeader()

setHeader

교환의 In 메시지에 지정된 헤더를 설정합니다.

setOutHeader()

setOutHeader

교환의 아웃 메시지에 지정된 헤더를 설정합니다.

setProperty()

setProperty()

지정된 교환 속성을 설정합니다.

sort()

정렬

메시지 본문 의 내용을 정렬합니다(사용자 지정 비교기를 선택적으로 지정할 수 있음).

split()

분할

8.4절. “Splitter”: 현재 교환을 일련의 교환으로 분할하여 각 분할 교환에는 원본 메시지 본문의 조각이 포함됩니다.

stop()

중지

현재 교환 라우팅을 중지하고 완료된 것으로 표시합니다.

threads()

스레드

경로의 마지막 부분을 동시에 처리하기 위한 스레드 풀을 생성합니다.

throttle()

throttle

8.8절. “Throttler”: 흐름 속도를 지정된 수준으로 제한합니다(초당 교환).

throwException()

throwException

지정된 Java 예외를 throw합니다.

to()

다음으로 변경

교환을 하나 이상의 엔드포인트로 전송합니다. 2.1절. “파이프라인 처리”을 참조하십시오.

toF()

해당 없음

문자열 형식을 사용하여 교환을 엔드포인트로 보냅니다. 즉, 엔드포인트 URI 문자열은 C Cryostat () 함수의 스타일에 대체를 포함할 수 있습니다.

transacted()

Transacted

경로의 마지막 부분을 포함하는 Spring 트랜잭션 범위를 생성합니다. Apache Karaf 트랜잭션 가이드를 참조하십시오.

transform()

transform

5.6절. “메시지#159”: 메시지 헤더를 Out 메시지 헤더에 복사하고 Out 메시지 본문을 지정된 값으로 설정합니다.

unmarshal()

unmarshal

지정된 데이터 형식을 사용하여 In 메시지 본문을 하위 수준 또는 바이너리 형식에서 상위 수준 형식으로 변환합니다.

validate()

검증

서술자 표현식을 사용하여 현재 메시지가 유효한지 여부를 테스트합니다. 서술자가 false 를 반환하면 PredicateValidationException 예외가 발생합니다.

wireTap()

wireTap

12.3절. “Wire Tap”: ExchangePattern.InOnly MEP를 사용하여 지정된 유선 탭 URI로 현재 교환의 사본을 보냅니다.

1.5.2. 일부 샘플 프로세서

경로에서 프로세서를 사용하는 방법에 대한 몇 가지 아이디어를 얻으려면 다음 예제를 참조하십시오.

1.5.3. 선택

choice() 프로세서는 들어오는 메시지를 대체 생산자 엔드포인트로 라우팅하는 데 사용되는 조건부 명령문입니다. 각 대체 생산자 끝점 앞에는 서술자 인수를 사용하는 when() 메서드 앞에 옵니다. 서술자가 true이면 다음 대상이 선택되고, 처리는 규칙에서 다음 when() 메서드로 진행됩니다. 예를 들어 다음 choice() 프로세서는 Predicate1Predicate2 의 값에 따라 수신 메시지를 Target1,Target2 또는 Target3 으로 보냅니다.

from("SourceURL")
    .choice()
        .when(Predicate1).to("Target1")
        .when(Predicate2).to("Target2")
        .otherwise().to("Target3");

Spring XML과 동일합니다.

<camelContext id="buildSimpleRouteWithChoice" xmlns="http://camel.apache.org/schema/spring">
  <route>
    <from uri="SourceURL"/>
    <choice>
      <when>
        <!-- First predicate -->
        <simple>header.foo = 'bar'</simple>
        <to uri="Target1"/>
      </when>
      <when>
        <!-- Second predicate -->
        <simple>header.foo = 'manchu'</simple>
        <to uri="Target2"/>
      </when>
      <otherwise>
        <to uri="Target3"/>
      </otherwise>
    </choice>
  </route>
</camelContext>

Java DSL에는 endChoice() 명령을 사용해야 할 수 있는 특수한 경우가 있습니다. 일부 표준 Apache Camel 프로세서를 사용하면 특수 하위 복제를 사용하여 추가 매개 변수를 지정할 수 있으며 일반적으로 end() 명령으로 종료되는 추가 중첩 수준을 효과적으로 열 수 있습니다. 예를 들어 로드 밸런서 절을 loadBalance().to("mock:foo").to("mock:bar").end() 로 지정할 수 있습니다. 그러나 로드 밸런서 절이 선택 조건에 포함된 경우 다음과 같이 endChoice() 명령을 사용하여 절을 종료해야 합니다.

from("direct:start")
    .choice()
        .when(bodyAs(String.class).contains("Camel"))
            .loadBalance().roundRobin().to("mock:foo").to("mock:bar").endChoice()
        .otherwise()
            .to("mock:result");

1.5.4. filter

filter() 프로세서는 관심 없는 메시지가 생산자 엔드포인트에 도달하지 못하도록 하는 데 사용할 수 있습니다. 단일 서술자 인수가 필요합니다. 서술자가 true이면 메시지 교환이 생산자를 통해 허용됩니다. 서술자가 false이면 메시지 교환이 차단됩니다. 예를 들어 다음 필터는 들어오는 메시지에 헤더를 포함하지 않는 한 메시지 교환을 차단합니다. foo 값은 bar 와 같습니다.

from("SourceURL").filter(header("foo").isEqualTo("bar")).to("TargetURL");

Spring XML과 동일합니다.

<camelContext id="filterRoute" xmlns="http://camel.apache.org/schema/spring">
  <route>
    <from uri="SourceURL"/>
    <filter>
      <simple>header.foo = 'bar'</simple>
      <to uri="TargetURL"/>
    </filter>
  </route>
</camelContext>

1.5.5. Throttler

throttle() 프로세서는 생산자 엔드포인트가 과부하되지 않도록 합니다. throttler는 초당 전달할 수 있는 메시지 수를 제한하여 작동합니다. 들어오는 메시지가 지정된 속도를 초과하면 throttler는 버퍼에서 초과 메시지를 누적하고 생산자 엔드포인트로 더 느리게 전송합니다. 예를 들어 처리량 속도를 초당 100개 메시지로 제한하려면 다음 규칙을 정의할 수 있습니다.

from("SourceURL").throttle(100).to("TargetURL");

Spring XML과 동일합니다.

<camelContext id="throttleRoute" xmlns="http://camel.apache.org/schema/spring">
  <route>
    <from uri="SourceURL"/>
    <throttle maximumRequestsPerPeriod="100" timePeriodMillis="1000">
      <to uri="TargetURL"/>
    </throttle>
  </route>
</camelContext>

1.5.6. 사용자 정의 프로세서

여기에 설명된 표준 프로세서 중 어느 것도 필요한 기능을 제공하지 않으면 항상 고유한 사용자 지정 프로세서를 정의할 수 있습니다. 사용자 지정 프로세서를 만들려면 org.apache.camel.Processor 인터페이스를 구현하고 process() 메서드를 재정의하는 클래스를 정의합니다. 다음 사용자 지정 프로세서인 MyProcessor 는 들어오는 메시지에서 foo 라는 헤더를 제거합니다.

예 1.3. 사용자 지정 프로세서 클래스 구현

public class MyProcessor implements org.apache.camel.Processor {
public void process(org.apache.camel.Exchange exchange) {
  inMessage = exchange.getIn();
  if (inMessage != null) {
      inMessage.removeHeader("foo");
  }
}
};

사용자 지정 프로세서를 라우터 규칙에 삽입하려면 프로세스에 프로세서를 삽입하는 일반적인 메커니즘을 제공하는 process() 메서드를 호출합니다. 예를 들어 다음 규칙은 예 1.3. “사용자 지정 프로세서 클래스 구현” 에 정의된 프로세서를 호출합니다.

org.apache.camel.Processor myProc = new MyProcessor();

from("SourceURL").process(myProc).to("TargetURL");

2장. 경로 빌드의 기본 사항

초록

Apache Camel은 경로에 함께 연결할 수 있는 여러 프로세서 및 구성 요소를 제공합니다. 이 장에서는 제공된 빌딩 블록을 사용하여 경로를 구축하는 원칙을 설명하는 기본 오리엔테이션을 제공합니다.

2.1. 파이프라인 처리

2.1.1. 개요

Apache Camel에서 파이프라이닝은 경로 정의에서 노드 연결을 위한 주요 패러다임입니다. 파이프라인 개념은 UNIX 운영 체제 사용자에게 가장 익숙할 수 있으며 운영 체제 명령을 결합하는 데 사용됩니다. 예를 들어 ls | more 는 디렉토리 목록 ls 를 page-scrolling 유틸리티로 파이프하는 명령의 예입니다. 파이프라인의 기본 개념은 한 명령의 출력이 다음 명령의 입력으로 제공됨입니다. 경로의 경우 자연 유추는 한 프로세서의 외부 메시지가 다음 프로세서의 In 메시지로 복사되는 것입니다.

2.1.2. 프로세서 노드

초기 엔드포인트를 제외한 경로의 모든 노드는 org.apache.camel.Processor 인터페이스에서 상속한다는 점에서 프로세서 입니다. 즉, 프로세서는 DSL 경로의 기본 빌딩 블록을 구성합니다. 예를 들어 filter(), delayer(), setBody(), setHeader()to() 와 같은 DSL 명령은 모두 프로세서를 나타냅니다. 프로세서가 경로를 구축하기 위해 함께 연결하는 방법을 고려할 때 두 가지 처리 방법을 구분하는 것이 중요합니다.

첫 번째 접근 방식은 프로세서가 그림 2.1. “메시지 내 수정 프로세서” 와 같이 교환의 In 메시지를 간단히 수정하는 것입니다. 이 경우 교환 외부 메시지는 null 로 유지됩니다.

그림 2.1. 메시지 내 수정 프로세서

메시지 내 프로세서 변경

다음 경로는 billingSystem 제목을 추가(또는 수정)하여 현재 In 메시지를 수정하는 setHeader() 명령을 보여줍니다.

from("activemq:orderQueue")
    .setHeader("BillingSystem", xpath("/order/billingSystem"))
    .to("activemq:billingQueue");

두 번째 접근 방식은 프로세서가 그림 2.2. “프로세서에서 출력 메시지 생성” 에 표시된 대로 처리 결과를 나타내는 Out 메시지를 생성하는 위치입니다.

그림 2.2. 프로세서에서 출력 메시지 생성

외부 메시지를 생성하는 프로세서

다음 경로는 문자열 DummyBody 가 포함된 메시지 본문을 사용하여 Out 메시지를 생성하는 transform() 명령을 보여줍니다.

from("activemq:orderQueue")
    .transform(constant("DummyBody"))
    .to("activemq:billingQueue");

여기서 constant("DummyBody") 는 상수 표현식을 나타냅니다. transform() 의 인수가 표현식 유형이어야 하므로 문자열 DummyBody 를 직접 전달할 수 없습니다.

2.1.3. InOnly 교환을 위한 파이프 라인

그림 2.3. “InOnly 교환을 위한 샘플 Pipeline” InOnly 교환을 위한 프로세서 파이프라인의 예를 보여줍니다. 프로세서 B 및 C는 출력 메시지를 생성하는 동안 In 메시지를 수정하여 작동합니다. 경로 빌더는 다음과 같이 프로세서를 함께 연결합니다. 특히 프로세서 B 및 C는 파이프라인 형태로 서로 연결되어 있습니다. 즉, 프로세서 B의 아웃 메시지가 프로세서 C로 전달되기 전에 In 메시지로 이동되고 프로세서 C의 아웃 메시지는 생산자 엔드포인트로 전환되기 전에 In 메시지로 이동합니다. 따라서 프로세서의 출력 및 입력은 그림 2.3. “InOnly 교환을 위한 샘플 Pipeline” 에 표시된 대로 연속 파이프라인에 결합됩니다.

그림 2.3. InOnly 교환을 위한 샘플 Pipeline

InOnly 교환을 위한 샘플 파이프라인

Apache Camel은 기본적으로 파이프라인 패턴을 사용하므로 경로에 파이프라인을 생성하는 데 특수 구문을 사용할 필요가 없습니다. 예를 들어 다음 경로는 userdataQueue 대기열에서 메시지를 가져오고 Velocity 템플릿을 통해 메시지를 파이프한 다음(텍스트 형식으로 고객 주소를 생성하기 위해) 결과 텍스트 주소를 큐로 보냅니다.

from("activemq:userdataQueue")
    .to(ExchangePattern.InOut, "velocity:file:AdressTemplate.vm")
    .to("activemq:envelopeAddresses");

Velocity 엔드포인트인 speed :file:AddressTemplate.vm 은 파일 시스템의 Velocity 템플릿 파일 file:AddressTemplate.vm 의 위치를 지정합니다. to() 명령은 교환을 Velocity 엔드포인트로 보내기 전에 교환 패턴을 InOut 로 변경한 다음 나중에 InOnly 로 다시 변경합니다. Velocity 엔드포인트에 대한 자세한 내용은 Apache Camel 구성 요소 참조 가이드의 Velocity 를 참조하십시오.

2.1.4. InOut 교환을 위한 파이프 라인

그림 2.4. “InOut Exchange를 위한 샘플 Pipeline” InOut 교환을 위한 프로세서 파이프라인의 예를 보여줍니다. 일반적으로 원격 프로시저 호출(RPC) 의미 체계를 지원하는 데 사용됩니다. 프로세서 A, B 및 C는 파이프라인 형태로 함께 연결되며 각 프로세서의 출력은 다음 프로세서의 입력으로 제공됩니다. 생산자 엔드포인트에 의해 생성된 최종 아웃 메시지는 소비자 엔드포인트로 다시 전송되며 원래 요청에 대한 응답을 제공합니다.

그림 2.4. InOut Exchange를 위한 샘플 Pipeline

InOut 교환을 위한 샘플 파이프라인

InOut 교환 패턴을 지원하려면 경로의 마지막 노드(프로덕터 엔드포인트 또는 다른 종류의 프로세서인지 여부)가 Out 메시지를 생성하는 것이 중요합니다. 그렇지 않으면 소비자 엔드포인트에 연결하는 모든 클라이언트가 중단되고 응답 메시지를 무기한 기다립니다. 모든 생산자 끝점이 Out 메시지를 생성하는 것은 아닙니다.

들어오는 HTTP 요청을 처리하여 결제 요청을 처리하는 다음 경로를 고려하십시오.

from("jetty:http://localhost:8080/foo")
    .to("cxf:bean:addAccountDetails")
    .to("cxf:bean:getCreditRating")
    .to("cxf:bean:processTransaction");

들어오는 결제 요청이 웹 서비스의 파이프라인을 통해 처리되는 경우 cxf:bean:addAccount Details,cxf:bean:getCreditRating, cxf:bean:processTransaction. 최종 웹 서비스인 processTransaction 은 JETTY 엔드포인트를 통해 다시 전송되는 응답(아웃 메시지)을 생성합니다.

파이프라인이 일련의 끝점으로 구성되면 다음 대체 구문을 사용할 수도 있습니다.

from("jetty:http://localhost:8080/foo")
    .pipeline("cxf:bean:addAccountDetails", "cxf:bean:getCreditRating", "cxf:bean:processTransaction");

2.1.5. InOptionalOut 교환 파이프라인

InOptionalOut 교환의 파이프라인은 기본적으로 그림 2.4. “InOut Exchange를 위한 샘플 Pipeline” 의 파이프라인과 동일합니다. InOutInOptionalOut 의 차이점은 InOptionalOut 교환 패턴과의 교환이 null Out 메시지를 회신으로 사용할 수 있다는 것입니다. 즉, InOptionalOut 교환의 경우 nullOut 메시지가 파이프라인에 있는 다음 노드의 In 메시지에 복사됩니다. 반대로 InOut 교환의 경우 nullOut 메시지가 삭제되고 현재 노드의 원래 In 메시지가 대신 다음 노드의 In 메시지로 복사됩니다.

2.2. 여러 입력

2.2.1. 개요

표준 경로는 Java DSL의 from(EndpointURL) 구문을 사용하여 단일 끝점에서만 입력을 가져옵니다. 그러나 경로에 대한 여러 입력을 정의해야 하는 경우 어떻게 해야 합니까? Apache Camel은 경로에 여러 입력을 지정할 수 있는 몇 가지 대안을 제공합니다. 이러한 접근 방식은 교환을 서로 독립적으로 처리할지 또는 서로 다른 입력의 교환을 어떤 방식으로든 결합할지 여부(이 경우 “콘텐츠 강화 패턴”를 사용해야 함)에 따라 달라집니다.

2.2.2. 여러 독립 입력

여러 입력을 지정하는 가장 간단한 방법은 from() DSL 명령의 다중 배열 형식을 사용하는 것입니다. 예를 들면 다음과 같습니다.

from("URI1", "URI2", "URI3").to("DestinationUri");

또는 다음과 같은 구문을 사용할 수 있습니다.

from("URI1").from("URI2").from("URI3").to("DestinationUri");

이 두 예에서 입력 끝점, URI1,URI2URI3 간의 교환은 서로 독립적으로 그리고 별도의 스레드에서 처리됩니다. 실제로 이전 경로를 다음 세 개의 별도의 경로와 동일한 것으로 간주할 수 있습니다.

from("URI1").to("DestinationUri");
from("URI2").to("DestinationUri");
from("URI3").to("DestinationUri");

2.2.3. 분할된 경로

예를 들어 두 개의 다른 메시징 시스템에서 들어오는 메시지를 병합하고 동일한 경로를 사용하여 처리할 수 있습니다. 대부분의 경우 그림 2.5. “세분화된 경로를 사용하여 여러 입력 처리” 에 표시된 대로 경로를 세그먼트로 분할하여 여러 입력을 처리할 수 있습니다.

그림 2.5. 세분화된 경로를 사용하여 여러 입력 처리

분할된 경로를 사용하여 여러 입력 처리

경로의 초기 세그먼트는 일부 외부 대기열에서 입력을 가져옵니다.예: activemq:Nyseactivemq:Nasdaq Cryostat-이자 내부 끝점으로 들어오는 교환을 내부 끝점으로 보냅니다. 두 번째 경로 세그먼트는 들어오는 교환을 병합하여 내부 엔드포인트에서 가져 와서 대상 대기열 activemq:USTxn 으로 전송합니다. InternalUrl 은 라우터 애플리케이션 내에서 사용하기 위한 끝점의 URL입니다. 다음 유형의 끝점은 내부 용도에 적합합니다.

이러한 끝점의 주요 목적은 경로의 다양한 세그먼트를 조합할 수 있도록 하는 것입니다. 모두 여러 입력을 단일 경로에 병합하는 효과적인 방법을 제공합니다.

2.2.4. 직접 끝점

직접 구성 요소는 경로를 연결하는 가장 간단한 메커니즘을 제공합니다. 직접 구성 요소의 이벤트 모델은 동기식 이므로 경로의 후속 세그먼트가 첫 번째 세그먼트와 동일한 스레드에서 실행됩니다. 직접 URL의 일반적인 형식은 direct:EndpointID 입니다. 여기서 끝점 ID, EndpointID 는 단순히 엔드포인트 인스턴스를 식별하는 고유한 영숫자 문자열입니다.

예를 들어 두 개의 메시지 대기열인 activemq:Nyseactivemq:Nasdaq 에서 입력을 가져와서 단일 메시지 큐인 activemq:USTxn 에 병합하려면 다음 경로 세트를 정의하여 이 작업을 수행할 수 있습니다.

from("activemq:Nyse").to("direct:mergeTxns");
from("activemq:Nasdaq").to("direct:mergeTxns");

from("direct:mergeTxns").to("activemq:USTxn");

여기서 처음 두 경로는 메시지 큐( NyseNasdaq )에서 입력을 가져와서 엔드포인트 direct:mergeTxns 로 보냅니다. 마지막 큐는 이전 두 큐의 입력을 결합하고 결합된 메시지 스트림을 activemq:USTxn 큐로 보냅니다.

직접 끝점의 구현은 다음과 같이 작동합니다. 교환이 생산자 끝점(예: to("direct:mergeTxns")에 도달할 때마다 직접 끝점은 동일한 끝점 ID가 있는 모든 소비자 끝점에 직접 교환을 전달합니다(예: from("direct:mergeTxns")). 직접 끝점은 동일한 JVM(Java 가상 머신) 인스턴스에서 동일한 CamelContext 에 속하는 경로 간 통신에만 사용할 수 있습니다.

2.2.5. SEDA 끝점

SEDA 구성 요소는 함께 경로를 연결하기 위한 대체 메커니즘을 제공합니다. 직접 구성 요소와 유사한 방식으로 사용할 수 있지만 다음과 같이 다른 기본 이벤트 및 스레딩 모델이 있습니다.

  • SEDA 엔드포인트 처리는 동기가 아닙니다. 즉, SEDA 생산자 엔드포인트에 교환을 보내면 제어가 경로의 이전 프로세서로 즉시 반환됩니다.
  • SEDA 끝점에는 다음 경로 세그먼트에 의해 처리되기 전에 들어오는 모든 교환을 저장하는 대기열 버퍼( java.util.concurrent.BlockingQueue 유형)가 포함되어 있습니다.
  • 각 SEDA 소비자 끝점은 스레드 풀을 생성하여 차단 대기열에서 교환 오브젝트를 처리합니다.
  • SEDA 구성 요소는 경쟁하는 소비자 패턴을 지원하므로 각 들어오는 교환이 특정 엔드포인트에 연결된 소비자가 여러 개 있어도 한 번만 처리됩니다.

SEDA 엔드포인트 사용의 주요 이점 중 하나는 경로가 내장 소비자 스레드 풀로 인해 응답성이 향상될 수 있다는 것입니다. 주식 거래 예는 다음과 같이 직접 끝점 대신 SEDA 끝점을 사용하도록 다시 작성할 수 있습니다.

from("activemq:Nyse").to("seda:mergeTxns");
from("activemq:Nasdaq").to("seda:mergeTxns");

from("seda:mergeTxns").to("activemq:USTxn");

이 예제와 직접 예제의 주요 차이점은 SEDA를 사용할 때 두 번째 경로 세그먼트( seda:mergeTxns 에서 activemq:USTxn)가 5개의 스레드 풀에서 처리된다는 것입니다.

참고

SEDA에는 단순히 경로 세그먼트를 붙여넣는 것보다 더 많은 것이 있습니다. 스테이징된 이벤트 중심 아키텍처(SEDA)는 보다 관리가 용이한 다중 스레드 애플리케이션을 빌드하기 위한 설계 철학을 포함합니다. Apache Camel의 SEDA 구성 요소는 간단히 이 설계 철학을 애플리케이션에 적용할 수 있도록 하는 것입니다. SEDA에 대한 자세한 내용은 http://www.eecs.harvard.edu/~mdw/proj/seda/ 을 참조하십시오.

2.2.6. VM 끝점

VM 구성 요소는 SEDA 엔드포인트와 매우 유사합니다. 유일한 차이점은 SEDA 구성 요소는 동일한 CamelContext 내에서 경로 세그먼트를 연결하는 반면 VM 구성 요소를 사용하면 동일한 Java 가상 시스템에서 실행되는 경우 별도의 Apache Camel 애플리케이션에서 경로를 함께 연결할 수 있다는 것입니다.

주식 거래 예는 다음과 같이 SEDA 끝점 대신 VM 끝점을 사용하도록 다시 작성할 수 있습니다.

from("activemq:Nyse").to("vm:mergeTxns");
from("activemq:Nasdaq").to("vm:mergeTxns");

또한 별도의 라우터 애플리케이션(동일 Java VM에서 실행)에서 다음과 같이 경로의 두 번째 세그먼트를 정의할 수 있습니다.

from("vm:mergeTxns").to("activemq:USTxn");

2.2.7. 콘텐츠 강화 패턴

컨텐츠 강화 패턴은 경로에 대한 여러 입력을 처리하는 근본적으로 다른 방법을 정의합니다. 교환이 강화 프로세서에 진입하면 보강된 정보는 정보를 검색하기 위해 외부 리소스에 연락한 다음 원래 메시지에 추가됩니다. 이 패턴에서 외부 리소스는 메시지에 대한 두 번째 입력을 효과적으로 나타냅니다.

예를 들어 신용 요청을 처리하는 애플리케이션을 작성하고 있다고 가정합니다. 신용 요청을 처리하기 전에 고객에게 신용 등급을 할당하는 데이터로 보강해야 합니다. 여기서 등급 데이터는 디렉터리의 src/data/ratings 파일에 저장됩니다. 다음과 같이 pollEnrich() 패턴과 GroupedExchangeAggregationStrategy 집계 전략을 사용하여 평가 파일의 데이터와 들어오는 신용 요청을 결합할 수 있습니다.

from("jms:queue:creditRequests")
    .pollEnrich("file:src/data/ratings?noop=true", new GroupedExchangeAggregationStrategy())
    .bean(new MergeCreditRequestAndRatings(), "merge")
    .to("jms:queue:reformattedRequests");

여기서 GroupedExchangeAggregationStrategy 클래스는 org.apache.camel.processor.aggregate 패키지의 표준 집계 전략이며 각 새 교환을 java.util.List 인스턴스에 추가하고 결과 목록을 Exchange.GROUPED_EXCHANGE exchange 속성에 저장합니다. 이 경우 목록에는 원래 교환( creditRequests JMS 큐에서)과 파일 엔드포인트에서 제공하는 강화 교환이라는 두 가지 요소가 포함되어 있습니다.

그룹화된 교환에 액세스하려면 다음과 같은 코드를 사용할 수 있습니다.

public class MergeCreditRequestAndRatings {
    public void merge(Exchange ex) {
        // Obtain the grouped exchange
        List<Exchange> list = ex.getProperty(Exchange.GROUPED_EXCHANGE, List.class);

        // Get the exchanges from the grouped exchange
        Exchange originalEx = list.get(0);
        Exchange ratingsEx  = list.get(1);

        // Merge the exchanges
        ...
    }
}

이 애플리케이션의 대체 방법은 병합 코드를 사용자 지정 집계 전략 클래스의 구현에 직접 배치하는 것입니다.

콘텐츠 강화 패턴에 대한 자세한 내용은 10.1절. “콘텐츠 Enricher” 을 참조하십시오.

2.3. 예외 처리

초록

Apache Camel은 다양한 수준의 세분성에서 예외를 처리할 수 있는 여러 가지 메커니즘을 제공합니다. doTry를 사용하여 경로 내에서 예외를 처리할 수 있습니다. doTry,doCatch, doFinally; 또는 각 예외 유형에 대해 수행할 작업을 지정하고 이 규칙을 Exception 을 사용하여 RouteBuilder 의 모든 경로에 적용할 수 있습니다. 또는 모든 예외 유형에 대해 수행할 작업을 지정하고 errorHandler 를 사용하여 RouteBuilder 의 모든 경로에 이 규칙을 적용할 수 있습니다.

예외 처리에 대한 자세한 내용은 6.3절. “dead Letter Channel” 을 참조하십시오.

2.3.1. onException

2.3.1.1. 개요

onException 절은 하나 이상의 경로에서 발생하는 예외를 트래핑하기 위한 강력한 메커니즘입니다. 즉, 유형별로 다른 예외 유형을 처리할 수 있는 고유한 작업을 정의할 수 있습니다. 따라서 기본적으로 동일한(실제로 확장) 구문을 사용하여 작업을 정의할 수 있으므로 예외를 처리하는 방식에 상당한 유연성을 제공하고 예외를 처리하는 방식에 상당한 유연성을 제공하고, 예외를 처리할 수 있습니다.

2.3.1.2. onException을 사용하여 예외를 트래핑

onException 절은 예외를 catch하는 대신 트래핑 을 위한 메커니즘입니다. 즉, onException 절을 정의하면 경로의 모든 지점에서 발생하는 예외를 트랩합니다. 이는 특정 코드 조각이 try 블록으로 명시적으로 묶은 경우에만 예외가 발생하는 Java try/catch 메커니즘과 대조됩니다.

onException 절을 정의할 때 실제로 발생하는 것은 Apache Camel 런타임이 try 블록의 각 경로 노드를 암시적으로 묶는 것입니다. 따라서 onException 절은 경로의 어느 시점에서 예외를 트래킹할 수 있습니다. 그러나 이 래핑은 자동으로 수행됩니다. 경로 정의에는 표시되지 않습니다.

2.3.1.3. Java DSL 예

다음 Java DSL 예제에서 onException 절은 RouteBuilder 클래스에 정의된 모든 경로에 적용됩니다. If a ValidationException exception occurs while processing either of the routes (from("seda:inputA") or from("seda:inputB"), the onException clause traps the exception and redirects the current exchange to the validationFailed JMS queue (which serves as a deadletter queue).

// Java
public class MyRouteBuilder extends RouteBuilder {

  public void configure() {
    onException(ValidationException.class)
      .to("activemq:validationFailed");

    from("seda:inputA")
      .to("validation:foo/bar.xsd", "activemq:someQueue");

    from("seda:inputB").to("direct:foo")
      .to("rnc:mySchema.rnc", "activemq:anotherQueue");
  }
}

2.3.1.4. XML DSL 예

위 예제는 다음과 같이 onException 요소를 사용하여 예외 절을 정의하는 XML DSL로 표시할 수도 있습니다.

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:camel="http://camel.apache.org/schema/spring"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
    http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">

    <camelContext xmlns="http://camel.apache.org/schema/spring">
        <onException>
            <exception>com.mycompany.ValidationException</exception>
            <to uri="activemq:validationFailed"/>
        </onException>
        <route>
            <from uri="seda:inputA"/>
            <to uri="validation:foo/bar.xsd"/>
            <to uri="activemq:someQueue"/>
        </route>
        <route>
            <from uri="seda:inputB"/>
            <to uri="rnc:mySchema.rnc"/>
            <to uri="activemq:anotherQueue"/>
        </route>
    </camelContext>

</beans>

2.3.1.5. 여러 예외를 트랩

RouteBuilder 범위에서 예외를 해결하기 위해 여러 onException 절을 정의할 수 있습니다. 이를 통해 다양한 예외에 대한 응답으로 다양한 작업을 수행할 수 있습니다. 예를 들어 Java DSL에 정의된 다음과 같은 onException 절에서는 ValidationException,IOExceptionException 에 대해 서로 다른 deadletter 대상을 정의합니다.

onException(ValidationException.class).to("activemq:validationFailed");
onException(java.io.IOException.class).to("activemq:ioExceptions");
onException(Exception.class).to("activemq:exceptions");

다음과 같이 XML DSL에서 동일한 일련의 onException 절을 정의할 수 있습니다.

<onException>
    <exception>com.mycompany.ValidationException</exception>
    <to uri="activemq:validationFailed"/>
</onException>
<onException>
    <exception>java.io.IOException</exception>
    <to uri="activemq:ioExceptions"/>
</onException>
<onException>
    <exception>java.lang.Exception</exception>
    <to uri="activemq:exceptions"/>
</onException>

여러 예외를 함께 그룹화하여 동일한 onException 절에 의해 갇힐 수도 있습니다. Java DSL에서는 다음과 같이 여러 예외를 그룹화할 수 있습니다.

onException(ValidationException.class, BuesinessException.class)
  .to("activemq:validationFailed");

XML DSL에서는 다음과 같이 onException 요소 내에 두 개 이상의 예외 요소를 정의하여 함께 여러 예외를 그룹화할 수 있습니다.

<onException>
    <exception>com.mycompany.ValidationException</exception>
    <exception>com.mycompany.BuesinessException</exception>
    <to uri="activemq:validationFailed"/>
</onException>

여러 예외를 트랩핑할 때 onException 절의 순서가 중요합니다. Apache Camel은 처음에 첫 번째 절에 대해 throw된 예외와 일치하려고 시도합니다. 첫 번째 절이 일치되지 않으면 다음 onException 절이 시도된 후 일치 항목이 발견될 때까지 계속 실행됩니다. 일치하는 각 시도는 다음 알고리즘에 의해 관리됩니다.

  1. throw된 예외가 체인된 예외 (즉, 예외가 catch되고 다른 예외로 다시 탐색된 경우)인 경우 가장 중첩된 예외 유형은 처음에 일치의 기반으로 사용됩니다. 이 예외는 다음과 같이 테스트됩니다.

    1. 예외-투-테스트에 정확히 onException 절에 지정된 형식이 있는 경우( 인스턴스를사용하여 테스트됨) 일치가 트리거됩니다.
    2. 예외-투-테스트가 onException 절에 지정된 형식의 하위 유형인 경우 일치가 트리거됩니다.
  2. 가장 중첩된 예외가 일치를 산출하지 못하면 체인의 다음 예외(래핑 예외)가 대신 테스트됩니다. 테스트는 일치가 트리거되거나 체인이 소진될 때까지 체인을 계속합니다.
참고

throwException EIP를 사용하면 간단한 언어 표현식에서 새 예외 인스턴스를 만들 수 있습니다. 예를 들어 현재 교환에서 사용 가능한 정보를 기반으로 동적으로 만들 수 있습니다.

<throwException exceptionType="java.lang.IllegalArgumentException" message="${body}"/>

2.3.1.6. Deadletter 채널

onException 사용의 기본 예제는 지금까지 모두 deadletter 채널 패턴을 악용했습니다. 즉, onException 절이 예외를 트래핑할 때 현재 교환은 특수 대상(종종 채널)으로 라우팅됩니다. deadletter 채널은 처리되지 않은 실패한 메시지의 보관 영역 역할을 합니다. 관리자는 나중에 메시지를 검사하고 어떤 작업을 수행해야 하는지 결정할 수 있습니다.

deadletter 채널 패턴에 대한 자세한 내용은 6.3절. “dead Letter Channel” 을 참조하십시오.

2.3.1.7. 원본 메시지 사용

경로 중간에서 예외가 발생하는 시점에, 교환의 메시지는 상당히 수정될 수 있었습니다(하나의 사람이 읽을 수도 있음). 경로 시작 시 수신되는 대로 문자 큐에 표시되는 메시지가 원본 메시지인 경우 관리자가 수행할 수정 작업을 보다 쉽게 결정할 수 있습니다. useOriginalMessage 옵션은 기본적으로 false 이지만 오류 처리기에 구성된 경우 자동으로 활성화됩니다.

참고

useOriginalMessage 옵션을 사용하면 여러 끝점에 메시지를 보내거나 메시지를 부분으로 분할하는 Camel 경로에 적용할 때 예기치 않은 동작이 발생할 수 있습니다. 중간 처리 단계가 원래 메시지를 수정하는 Multicast, Splitter 또는 RecipientList 경로에 원래 메시지가 유지되지 않을 수 있습니다.

Java DSL에서는 교환에서 메시지를 원래 메시지로 교체할 수 있습니다. setAllowUseOriginalMessage()true 로 설정한 다음 다음과 같이 useOriginalMessage() DSL 명령을 사용합니다.

onException(ValidationException.class)
  .useOriginalMessage()
  .to("activemq:validationFailed");

XML DSL에서는 다음과 같이 onException 요소에서 useOriginalMessage 특성을 설정하여 원본 메시지를 검색할 수 있습니다.

<onException useOriginalMessage="true">
    <exception>com.mycompany.ValidationException</exception>
    <to uri="activemq:validationFailed"/>
</onException>
참고

setAllowUseOriginalMessage() 옵션이 true 로 설정된 경우 Camel은 경로 시작 시 원본 메시지의 사본을 작성하여 useOriginalMessage() 를 호출할 때 원래 메시지를 사용할 수 있도록 합니다. 그러나 Camel 컨텍스트에서 setAllowUseOriginalMessage() 옵션이 false (기본값)로 설정된 경우 원래 메시지에 액세스할 수 없으며 useOriginalMessage() 를 호출할 수 없습니다.

기본 동작을 악용하는 이유는 대규모 메시지를 처리할 때 성능을 최적화하는 것입니다.

2.18 이전 Camel 버전에서는 allowUseOriginalMessage 의 기본 설정은 true입니다.

2.3.1.8. Redelivery policy

메시지 처리를 중단하고 예외가 발생하는 즉시 포기하는 대신 Apache Camel은 예외가 발생한 시점에서 메시지를 다시 전달할 수 있는 옵션을 제공합니다. 시간 초과가 발생하고 일시적인 오류가 발생하는 네트워크 시스템에서는 원래 예외가 발생한 직후에 실패한 메시지가 성공적으로 처리될 수 있는 경우가 많습니다.

Apache Camel 재전송은 예외가 발생한 후 메시지를 재전송하기 위한 다양한 전략을 지원합니다. 재전송을 구성하는 가장 중요한 옵션 중 일부는 다음과 같습니다.

maximumRedeliveries()
재전송할 수 있는 최대 횟수를 지정합니다(기본값은 0). 음수 값은 재전송이 항상 시도됨을 의미합니다(무제한 값과 동일).
retryWhile()

Apache Camel의 계속 재전송 여부를 결정하는 서술자(예: Predicate 유형)를 지정합니다. 서술자가 현재 교환에서 true 로 평가되면 재전송이 시도됩니다. 그렇지 않으면 재전송이 중지되고 추가 재전송 시도가 수행되지 않습니다.

이 옵션은 maximumRedeliveries() 옵션보다 우선합니다.

Java DSL에서 redelivery 정책 옵션은 onException 절의 DSL 명령을 사용하여 지정됩니다. 예를 들어 다음과 같이 교환이 validationFailed deadletter 큐로 전송되는 최대 6개의 재전송을 지정할 수 있습니다.

onException(ValidationException.class)
  .maximumRedeliveries(6)
  .retryAttemptedLogLevel(org.apache.camel.LogginLevel.WARN)
  .to("activemq:validationFailed");

XML DSL에서 redeliveryPolicy 요소에 속성을 설정하여 재전송 정책 옵션이 지정됩니다. 예를 들어 이전 경로는 다음과 같이 XML DSL로 표시할 수 있습니다.

<onException useOriginalMessage="true">
    <exception>com.mycompany.ValidationException</exception>
    <redeliveryPolicy maximumRedeliveries="6"/>
    <to uri="activemq:validationFailed"/>
</onException>

재전송 옵션은 마지막 재전송 시도가 실패 할 때까지 재전송 옵션이 설정되지 않은 후 경로의 후의 후. 모든 재전송 옵션에 대한 자세한 설명은 6.3절. “dead Letter Channel” 을 참조하십시오.

또는 redeliveryPolicyProfile 인스턴스에서 재전송 정책 옵션을 지정할 수 있습니다. 그런 다음 onException 요소의 redeliverPolicyRef 특성을 사용하여 redeliveryPolicyProfile 인스턴스를 참조할 수 있습니다. 예를 들어 이전 경로는 다음과 같이 표시할 수 있습니다.

<redeliveryPolicyProfile id="redelivPolicy" maximumRedeliveries="6" retryAttemptedLogLevel="WARN"/>

<onException useOriginalMessage="true" redeliveryPolicyRef="redelivPolicy">
    <exception>com.mycompany.ValidationException</exception>
    <to uri="activemq:validationFailed"/>
</onException>
참고

redeliveryPolicyProfile 을 사용하는 방법은 여러 onException 절에서 동일한 재전송 정책을 다시 사용하려는 경우 유용합니다.

2.3.1.9. 조건부 트래핑

onException 을 사용한 예외 트래핑은 on When 옵션을 지정하여 조건부로 수행할 수 있습니다. onException 절에서 onIf 옵션을 지정하면 throw된 예외가 해당 절 일치하고 현재 교환 에서 true 로 평가되는 경우에만 일치가 트리거됩니다.

예를 들어 다음 Java DSL 조각에서 throw된 예외가 MyUserException 과 일치하고 현재 교환에서 사용자 헤더가 null이 아닌 경우에만 첫 번째 onException 절이 트리거됩니다.

// Java

// Here we define onException() to catch MyUserException when
// there is a header[user] on the exchange that is not null
onException(MyUserException.class)
    .onWhen(header("user").isNotNull())
    .maximumRedeliveries(2)
    .to(ERROR_USER_QUEUE);

// Here we define onException to catch MyUserException as a kind
// of fallback when the above did not match.
// Noitce: The order how we have defined these onException is
// important as Camel will resolve in the same order as they
// have been defined
onException(MyUserException.class)
    .maximumRedeliveries(2)
    .to(ERROR_QUEUE);

위의 onException 절은 다음과 같이 XML DSL로 표시할 수 있습니다.

<redeliveryPolicyProfile id="twoRedeliveries" maximumRedeliveries="2"/>

<onException redeliveryPolicyRef="twoRedeliveries">
    <exception>com.mycompany.MyUserException</exception>
    <onWhen>
        <simple>${header.user} != null</simple>
    </onWhen>
    <to uri="activemq:error_user_queue"/>
</onException>

<onException redeliveryPolicyRef="twoRedeliveries">
    <exception>com.mycompany.MyUserException</exception>
    <to uri="activemq:error_queue"/>
</onException>

2.3.1.10. 예외 처리

기본적으로 경로 중간에서 예외가 발생하는 경우 현재 교환 처리가 중단되고 경로 시작 시 throw된 예외가 소비자 끝점으로 다시 전파됩니다. onException 절이 트리거되면 throw된 예외가 다시 전파되기 전에 onException 절이 일부 처리를 수행하는 경우를 제외하고 기본적으로 동작이 동일합니다.

그러나 이 기본 동작은 예외를 처리하는 유일한 방법은 아닙니다. onException 은 다음과 같이 예외 처리 동작을 수정하는 다양한 옵션을 제공합니다.

  • onException 절이 완료된 후 취소 예외를 억제하는 옵션이 있습니다. ??? 즉, 이 경우 예외는 경로 시작 시 소비자 끝점으로 다시 전파 되지 않습니다.
  • 계속 처리 의 경우 예외가 원래 발생한 시점에서 교환의 정상적인 처리를 다시 시작할 수 있습니다. 암시적으로 이 방법은 rethrown 예외도 표시하지 않습니다.
  • 경로 시작 시 소비자 끝점이 응답을 예상하는 특수한 경우(즉, InOut MEP가 있음) 예외를 소비자 엔드포인트로 다시 전파하는 대신 사용자 지정 오류 응답 메시지를 생성하는 것을 선호할 수 있습니다.

2.3.1.11. 예외 취소 비활성화

현재 예외가 다시 생성되고 소비자 끝점으로 다시 전파되지 않도록 하려면 다음과 같이 Java DSL에서 handled() 옵션을 true 로 설정할 수 있습니다.

onException(ValidationException.class)
  .handled(true)
  .to("activemq:validationFailed");

Java DSL에서 handled() 옵션에 대한 인수는 부울 유형, Predicate 유형 또는 Expression 유형 중 하나일 수 있습니다(boolean 이외의 표현식이 null 이외의 값으로 평가되면).

다음과 같이 처리된 요소를 사용하여 XML DSL에서 rethrown 예외를 억제하도록 동일한 경로를 구성할 수 있습니다.

<onException>
    <exception>com.mycompany.ValidationException</exception>
    <handled>
        <constant>true</constant>
    </handled>
    <to uri="activemq:validationFailed"/>
</onException>

2.3.1.12. 계속 처리

예외가 원래 throw된 경로 지점에서 현재 메시지를 계속 처리하려면 다음과 같이 Java DSL에서 지속적인 옵션을 true 로 설정할 수 있습니다.

onException(ValidationException.class)
  .continued(true);

Java DSL에서 continued() 옵션에 대한 인수는 부울 유형, Predicate 유형 또는 Expression 유형일 수 있습니다(모든 비boolean 표현식이 true 로 해석되는 경우 null이 아닌 값으로 평가되는 경우).

계속되는 요소를 사용하여 다음과 같이 XML DSL에서 동일한 경로를 구성할 수 있습니다.

<onException>
    <exception>com.mycompany.ValidationException</exception>
    <continued>
        <constant>true</constant>
    </continued>
</onException>

2.3.1.13. 응답 전송

경로를 시작하는 소비자 끝점에 회신이 필요한 경우 throw된 예외가 소비자에게 다시 전파되도록 하는 대신 사용자 정의 오류 응답 메시지를 구성하는 것을 선호할 수 있습니다. 이 경우 수행해야 하는 두 가지 필수 단계가 있습니다. 즉, 처리된 옵션을 사용하여 복구 예외를 표시하지 않고 교환의 Out 메시지 슬롯을 사용자 지정 오류 메시지로 채웁니다.

예를 들어 다음 Java DSL 조각은 MyFunctionalException 예외가 발생할 때마다 텍스트 문자열 Sorry 가 포함된 응답 메시지를 보내는 방법을 보여줍니다.

// we catch MyFunctionalException and want to mark it as handled (= no failure returned to client)
// but we want to return a fixed text response, so we transform OUT body as Sorry.
onException(MyFunctionalException.class)
    .handled(true)
    .transform().constant("Sorry");

클라이언트에 오류 응답을 보내는 경우 응답에 예외 메시지의 텍스트를 통합하려는 경우가 많습니다. exceptionMessage() builder 메서드를 사용하여 현재 예외 메시지의 텍스트에 액세스할 수 있습니다. 예를 들어 다음과 같이 MyFunctionalException 예외가 발생할 때마다 예외 메시지의 텍스트가 포함된 응답을 보낼 수 있습니다.

// we catch MyFunctionalException and want to mark it as handled (= no failure returned to client)
// but we want to return a fixed text response, so we transform OUT body and return the exception message
onException(MyFunctionalException.class)
    .handled(true)
    .transform(exceptionMessage());

예외 메시지 텍스트는 exception.message 변수를 통해 Simple 언어에서도 액세스할 수 있습니다. 예를 들어 다음과 같이 응답 메시지에 현재 예외 텍스트를 포함할 수 있습니다.

// we catch MyFunctionalException and want to mark it as handled (= no failure returned to client)
// but we want to return a fixed text response, so we transform OUT body and return a nice message
// using the simple language where we want insert the exception message
onException(MyFunctionalException.class)
    .handled(true)
    .transform().simple("Error reported: ${exception.message} - cannot process this message.");

위의 onException 절은 다음과 같이 XML DSL로 표현될 수 있습니다.

<onException>
    <exception>com.mycompany.MyFunctionalException</exception>
    <handled>
        <constant>true</constant>
    </handled>
    <transform>
        <simple>Error reported: ${exception.message} - cannot process this message.</simple>
    </transform>
</onException>

2.3.1.14. 예외를 처리하는 동안 throw되는 예외

기존 예외를 처리하는 동안 throw되는 예외(즉, onException 절 처리 중에서 throw되는 예외)는 특별한 방식으로 처리됩니다.An exception that gets thrown while handling an existing exception (in other words, one that gets thrown in the middle of processing an onException clause) is handled in a special way. 이러한 예외는 다음과 같이 예외를 처리하는 특수 대체 예외 처리기에 의해 처리됩니다.

  • 기존 예외 처리기는 모두 무시되고 처리가 즉시 실패합니다.
  • 새 예외가 기록됩니다.
  • 새로운 예외는 교환 오브젝트에 설정됩니다.

간단한 전략은 onException 절이 무한 루프에 고정되는 상태로 끝날 수 있는 복잡한 실패 시나리오를 방지합니다.

2.3.1.15. 범위

onException 절은 다음 범위 중 하나에서 효과적일 수 있습니다.

  • RouteBuilder 범위 cidr- onException 절은 RouteBuilder.configure() 메서드 내의 독립 실행형 문으로 정의된 모든 RouteBuilder 인스턴스에 정의된 모든 경로에 영향을 미칩니다. 반면, 이러한 onException 절은 다른 RouteBuilder 인스턴스 내에 정의된 경로에 영향을 미치지 않습니다. onException 절은 경로 정의 앞에 표시되어야 합니다.

    이 시점까지의 모든 예제는 RouteBuilder 범위를 사용하여 정의됩니다.

  • 경로 범위 Cryostat- onException 절을 경로 내에 직접 포함할 수도 있습니다. 이러한 onException 절은 정의된 경로에 영향을 미칩니다.

2.3.1.16. 경로 범위

경로 정의 내부에 onException 절을 포함할 수 있지만 end() DSL 명령을 사용하여 포함된 onException 절을 종료해야 합니다.

예를 들어 다음과 같이 Java DSL에 포함된 onException 절을 정의할 수 있습니다.

// Java
from("direct:start")
  .onException(OrderFailedException.class)
    .maximumRedeliveries(1)
    .handled(true)
    .beanRef("orderService", "orderFailed")
    .to("mock:error")
  .end()
  .beanRef("orderService", "handleOrder")
  .to("mock:result");

다음과 같이 XML DSL에 포함된 onException 절을 정의할 수 있습니다.

<route errorHandlerRef="deadLetter">
    <from uri="direct:start"/>
    <onException>
        <exception>com.mycompany.OrderFailedException</exception>
        <redeliveryPolicy maximumRedeliveries="1"/>
        <handled>
            <constant>true</constant>
        </handled>
        <bean ref="orderService" method="orderFailed"/>
        <to uri="mock:error"/>
    </onException>
    <bean ref="orderService" method="handleOrder"/>
    <to uri="mock:result"/>
</route>

2.3.2. 오류 처리기

2.3.2.1. 개요

errorHandler() 절은 onException 절과 유사한 기능을 제공합니다. 단, 이 메커니즘은 다른 예외 유형을 구별할 수 없습니다. errorHandler() 절은 Apache Camel에서 제공하는 원래 예외 처리 메커니즘이며 onException 절이 구현되기 전에 사용할 수 있었습니다.

2.3.2.2. Java DSL 예

errorHandler() 절은 RouteBuilder 클래스에 정의되어 있으며 해당 RouteBuilder 클래스의 모든 경로에 적용됩니다. 적용 가능한 경로 중 하나에서 모든 종류의 예외가 발생할 때마다 트리거됩니다. 예를 들어 실패한 모든 교환을 ActiveMQ deadLetter 큐로 라우팅하는 오류 처리기를 정의하려면 다음과 같이 RouteBuilder 를 정의할 수 있습니다.

public class MyRouteBuilder extends RouteBuilder {

    public void configure() {
        errorHandler(deadLetterChannel("activemq:deadLetter"));

        // The preceding error handler applies
        // to all of the following routes:
        from("activemq:orderQueue")
          .to("pop3://fulfillment@acme.com");
        from("file:src/data?noop=true")
          .to("file:target/messages");
        // ...
    }
}

그러나 dead letter channel으로의 리디렉션은 다시 전송 시 모든 시도가 소진될 때까지 발생하지 않습니다.

2.3.2.3. XML DSL 예

XML DSL에서는 errorHandler 요소를 사용하여 camelContext 범위 내에 오류 처리기를 정의합니다. 예를 들어 실패한 모든 교환을 ActiveMQ deadLetter 큐로 라우팅하는 오류 처리기를 정의하려면 다음과 같이 errorHandler 요소를 정의할 수 있습니다.

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:camel="http://camel.apache.org/schema/spring"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
    http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">

    <camelContext xmlns="http://camel.apache.org/schema/spring">
        <errorHandler type="DeadLetterChannel"
                      deadLetterUri="activemq:deadLetter"/>
        <route>
            <from uri="activemq:orderQueue"/>
            <to uri="pop3://fulfillment@acme.com"/>
        </route>
        <route>
            <from uri="file:src/data?noop=true"/>
            <to uri="file:target/messages"/>
        </route>
    </camelContext>

</beans>

2.3.2.4. 오류 처리기 유형

표 2.1. “오류 처리기 유형” 정의할 수 있는 다양한 유형의 오류 처리기에 대한 개요를 제공합니다.

표 2.1. 오류 처리기 유형

Java DSL BuilderXML DSL 유형 속성설명

defaultErrorHandler()

DefaultErrorHandler

예외를 호출자로 다시 전파하고 재전송 정책을 지원하지만 dead letter 큐는 지원하지 않습니다.

deadLetterChannel()

DeadLetterChannel

기본 오류 처리기와 동일한 기능을 지원하며, 또한 dead letter 큐를 지원합니다.

loggingErrorChannel()

LoggingErrorChannel

예외가 발생할 때마다 예외 텍스트를 기록합니다.

noErrorHandler()

NoErrorHandler

오류 처리기를 비활성화하는 데 사용할 수 있는 더미 처리기 구현입니다.

 

TransactionErrorHandler

트랜잭션된 경로에 대한 오류 처리기입니다. 트랜잭션으로 표시된 경로에 기본 트랜잭션 오류 처리기 인스턴스가 자동으로 사용됩니다.

2.3.3. DoTry, doCatch 및 doFinally

2.3.3.1. 개요

경로 내에서 예외를 처리하기 위해 doTry,doCatchdoFinally 절을 조합하여 Java의 시도,catch, finally 블록과 유사한 방식으로 예외를 처리할 수 있습니다.

2.3.3.2. doCatch와 Java catch 간의 유사점

일반적으로 경로 정의의 doCatch() 절은 Java 코드에서 catch() 문과 유사한 방식으로 작동합니다. 특히 doCatch() 절에서 다음 기능을 지원합니다.

  • 하나의 do Try 블록 내에 여러 doCatch 절을 사용할 수 있습니다. doCatch 절은 Java catch() 문과 마찬가지로 표시되는 순서대로 테스트됩니다. Apache Camel은 throw된 예외와 일치하는 첫 번째 doCatch 절을 실행합니다.

    참고

    이 알고리즘은 onException 절에서 사용하는 예외 일치 알고리즘과 다릅니다. 자세한 내용은 2.3.1절. “onException” 을 참조하십시오.

  • 구문을 사용하여 doCatch 절 내에서 현재 예외를 다시 실행할 수 있습니다( “doCatch에서 예외 제거”참조).

2.3.3.3. doCatch의 특수 기능

그러나 Java catch() 문에 유사한 기능이 없는 doCatch() 절의 몇 가지 특수 기능이 있습니다. 다음 기능은 doCatch() 에만 적용됩니다.

2.3.3.4. 예제

다음 예제에서는 Java DSL에 doTry 블록을 작성하는 방법을 보여줍니다. 여기서 doCatch() 절이 실행되는 경우 IOException 예외 또는 IllegalStateException 예외가 발생되고 예외가 발생했는지 여부에 관계없이 doFinally() 절이 항상 실행됩니다.

from("direct:start")
    .doTry()
        .process(new ProcessorFail())
        .to("mock:result")
    .doCatch(IOException.class, IllegalStateException.class)
        .to("mock:catch")
    .doFinally()
        .to("mock:finally")
    .end();

또는 이와 동등한 경우 Spring XML:

<route>
    <from uri="direct:start"/>
    <!-- here the try starts. its a try .. catch .. finally just as regular java code -->
    <doTry>
        <process ref="processorFail"/>
        <to uri="mock:result"/>
        <doCatch>
            <!-- catch multiple exceptions -->
            <exception>java.io.IOException</exception>
            <exception>java.lang.IllegalStateException</exception>
            <to uri="mock:catch"/>
        </doCatch>
        <doFinally>
            <to uri="mock:finally"/>
        </doFinally>
    </doTry>
</route>

2.3.3.5. doCatch에서 예외 제거

다음과 같이 구문을 사용하여 doCatch() 절에서 예외를 다시 시작할 수 있습니다.

from("direct:start")
    .doTry()
        .process(new ProcessorFail())
        .to("mock:result")
    .doCatch(IOException.class)
         .to("mock:io")
        // Rethrow the exception using a construct instead of handled(false) which is deprecated in a doTry/doCatch clause.
        .throwException(new IllegalArgumentException("Forced"))
    .doCatch(Exception.class)
        // Catch all other exceptions.
        .to("mock:error")
    .end();
참고

doTry/doCatch 절에서 더 이상 사용되지 않는 처리(false) 대신 프로세서를 사용하여 예외를 다시 시작할 수도 있습니다.

.process(exchange -> {throw exchange.getProperty(Exchange.EXCEPTION_CAUGHT, Exception.class);})

이전 예에서 IOExceptiondoCatch() 에 의해 catch되면 현재 교환이 mock:io 엔드포인트로 전송되고 IOException 이 다시 검색됩니다. 이렇게 하면 경로 시작 시 소비자 끝점( from() 명령)도 예외를 처리할 수 있습니다.

다음 예제에서는 Spring XML에서 동일한 경로를 정의하는 방법을 보여줍니다.

<route>
    <from uri="direct:start"/>
    <doTry>
        <process ref="processorFail"/>
        <to uri="mock:result"/>
        <doCatch>
            <to uri="mock:io"/>
            <throwException message="Forced" exceptionType="java.lang.IllegalArgumentException"/>
        </doCatch>
        <doCatch>
            <!-- Catch all other exceptions. -->
            <exception>java.lang.Exception</exception>
            <to uri="mock:error"/>
        </doCatch>
    </doTry>
</route>

2.3.3.6. on When 사용 중 조건부 예외 catching

Apache Camel doCatch() 절의 특수 기능은 런타임에 평가되는 표현식을 기반으로 예외 catch를 조건부화할 수 있다는 것입니다. 즉, 양식의 절을 사용하여 예외를 catch하는 경우 doCatch(ExceptionList).do When(Expression) 에서는 조건자 표현식, Expression, 런타임 시 true 로 평가되는 경우에만 예외가 catch됩니다.

예를 들어 다음 doTry 블록은 예외인 IOExceptionIllegalStateException 이 예외를 catch합니다. 예외 메시지에 단어 Severe 가 포함된 경우에만 마찬가지입니다.

from("direct:start")
    .doTry()
        .process(new ProcessorFail())
        .to("mock:result")
    .doCatch(IOException.class, IllegalStateException.class)
        .onWhen(exceptionMessage().contains("Severe"))
        .to("mock:catch")
    .doCatch(CamelExchangeException.class)
        .to("mock:catchCamel")
    .doFinally()
        .to("mock:finally")
    .end();

또는 이와 동등한 경우 Spring XML:

<route>
    <from uri="direct:start"/>
    <doTry>
        <process ref="processorFail"/>
        <to uri="mock:result"/>
        <doCatch>
            <exception>java.io.IOException</exception>
            <exception>java.lang.IllegalStateException</exception>
            <onWhen>
                <simple>${exception.message} contains 'Severe'</simple>
            </onWhen>
            <to uri="mock:catch"/>
        </doCatch>
        <doCatch>
            <exception>org.apache.camel.CamelExchangeException</exception>
            <to uri="mock:catchCamel"/>
        </doCatch>
        <doFinally>
            <to uri="mock:finally"/>
        </doFinally>
    </doTry>
</route>

2.3.3.7. doTry의 중첩된 조건

JavaDSL 경로에 Camel 예외 처리를 추가하는 데 사용할 수 있는 다양한 옵션이 있습니다. dotry() 는 예외를 처리하기 위한 try 또는 catch 블록을 생성하고 경로별 오류 처리에 유용합니다.

ChoiceDefinition 내에서 예외를 catch하려면 다음 doTry 블록을 사용할 수 있습니다.

from("direct:wayne-get-token").setExchangePattern(ExchangePattern.InOut)
           .doTry()
              .to("https4://wayne-token-service")
              .choice()
                  .when().simple("${header.CamelHttpResponseCode} == '200'")
                     .convertBodyTo(String.class)
.setHeader("wayne-token").groovy("body.replaceAll('\"','')")
                     .log(">> Wayne Token : ${header.wayne-token}")
                .endChoice()

.doCatch(java.lang.Class (java.lang.Exception>)
              .log(">> Exception")
           .endDoTry();

from("direct:wayne-get-token").setExchangePattern(ExchangePattern.InOut)
           .doTry()
              .to("https4://wayne-token-service")
           .doCatch(Exception.class)
              .log(">> Exception")
           .endDoTry();

2.3.4. Cryostat 예외 전파

2.3.4.1. 개요

Camel CXF 구성 요소는 Apache CXF와 통합되므로 Apache Camel 끝점에서 Cryostat 메시지를 보내고 받을 수 있습니다. XML로 Apache Camel 엔드포인트를 쉽게 정의할 수 있으며 엔드포인트의 8080 ID를 사용하여 경로에서 참조할 수 있습니다. 자세한 내용은 Apache Camel 구성 요소 참조 가이드의 CXF 를 참조하십시오.

2.3.4.2. 스택 추적 정보를 전파하는 방법

Java 예외가 서버 측에서 throw될 때 예외에 대한 스택 추적이 오류 메시지로 마샬링되어 클라이언트에 반환되도록 CXF 엔드포인트를 구성할 수 있습니다. 이 페어링을 사용하려면 dataFormatPAYLOAD 로 설정하고 cxfEndpoint 요소에서 faultStackTraceEnabled 속성을 true 로 설정합니다.

<cxf:cxfEndpoint id="router" address="http://localhost:9002/TestMessage"
    wsdlURL="ship.wsdl"
    endpointName="s:TestSoapEndpoint"
    serviceName="s:TestService"
    xmlns:s="http://test">
  <cxf:properties>
    <!-- enable sending the stack trace back to client; the default value is false-->
    <entry key="faultStackTraceEnabled" value="true" />
    <entry key="dataFormat" value="PAYLOAD" />
  </cxf:properties>
</cxf:cxfEndpoint>

보안상의 이유로 스택 추적에는 발생 예외가 포함되지 않습니다(즉, 에서 문제를 따르는 스택 추적의 일부). 스택 추적에 발생 예외를 포함하려면 다음과 같이 cxfEndpoint 요소에서 exceptionMessageCauseEnabled 속성을 true 로 설정합니다.

<cxf:cxfEndpoint id="router" address="http://localhost:9002/TestMessage"
    wsdlURL="ship.wsdl"
    endpointName="s:TestSoapEndpoint"
    serviceName="s:TestService"
    xmlns:s="http://test">
  <cxf:properties>
    <!-- enable to show the cause exception message and the default value is false -->
    <entry key="exceptionMessageCauseEnabled" value="true" />
    <!-- enable to send the stack trace back to client,  the default value is false-->
    <entry key="faultStackTraceEnabled" value="true" />
    <entry key="dataFormat" value="PAYLOAD" />
  </cxf:properties>
</cxf:cxfEndpoint>
주의

테스트 및 진단을 위해 exceptionMessageCauseEnabled 플래그만 활성화해야 합니다. 서버는 적대적인 사용자가 서버를 프로브하는 것을 더 어렵게 만들기 위해 예외의 원래 원인을 숨기는 것이 일반적인 방법입니다.

2.4. Cryostat 통합

2.4.1. 개요

Quarkus 통합은 임의의 Java 오브젝트를 사용하여 메시지를 처리하기 위한 일반적인 용도 메커니즘을 제공합니다. Quarkus 참조를 경로에 삽입하면 Java 오브젝트에서 임의의 메서드를 호출하여 들어오는 교환에 액세스하고 수정할 수 있습니다. exchange의 내용을 매개 변수에 매핑하고, 8080 메서드의 반환 값을 매개 변수 바인딩 이라고 합니다. 매개변수 바인딩은 메서드의 매개변수를 초기화하기 위해 다음 접근 방식의 조합을 사용할 수 있습니다.

  • 기존 메서드 서명 에서 메서드 시그니처가 특정 규칙을 준수하는 경우 매개 변수 바인딩은 Java 리플렉션을 사용하여 전달할 매개변수를 결정할 수 있습니다.
  • 더 유연한 바인딩 메커니즘의 경우 Java 주석을 사용하여 메서드의 인수에 삽입할 항목을 지정합니다. 이 종속성 주입 메커니즘은 Spring 2.5 구성 요소 검사에 의존합니다. 일반적으로 Apache Camel 애플리케이션을 Spring 컨테이너에 배포하는 경우 종속성 주입 메커니즘이 자동으로 작동합니다.
  • 명시적으로 지정된 매개 변수 Cryostat- Cryostat는 빈이 호출되는 시점에서 매개 변수를 상수 또는 Simple 언어를 사용하여 명시적으로 지정할 수 있습니다.

2.4.2. Cryostat 레지스트리

빈은 클래스 이름 또는 빈 ID를 키로 사용하여 빈을 조회할 수 있는 서비스인 8080 레지스트리 를 통해 액세스할 수 있습니다. 8080 레지스트리에서 항목을 생성하는 방법은 기본 프레임워크의 경우 일반 Java, Spring, Guice 또는 블루프린트에 따라 다릅니다. 레지스트리 항목은 일반적으로 암시적으로 생성됩니다(예: Spring XML 파일에서 Spring 8080을 인스턴스화할 때).

2.4.3. 레지스트리 플러그인 전략

Apache Camel은 8080 레지스트리에 대한 플러그인 전략을 구현하여 기본 레지스트리 구현을 투명하게 만드는 빈에 액세스하기 위한 통합 계층을 정의합니다. 따라서 표 2.2. “레지스트리 플러그인” 에 표시된 대로 다양한 다른 8080 레지스트리와 Apache Camel 애플리케이션을 통합할 수 있습니다.

표 2.2. 레지스트리 플러그인

레지스트리 구현레지스트리 플러그인이 포함된 Camel 구성 요소

Spring 8080 레지스트리

camel-spring

Guice metrics 레지스트리

camel-guice

블루프린트 8080 레지스트리

camel-blueprint

OSGi 서비스 레지스트리

OSGi 컨테이너에배포

JNDI 레지스트리

 

일반적으로 관련 8080 레지스트리가 자동으로 설치되므로 빈 레지스트리 구성에 대해 우려할 필요가 없습니다. 예를 들어 Spring 프레임워크를 사용하여 경로를 정의하는 경우 Spring ApplicationContextRegistry 플러그인이 현재 CamelContext 인스턴스에 자동으로 설치됩니다.

OSGi 컨테이너의 배포는 특수한 사례입니다. Apache Camel 경로가 OSGi 컨테이너에 배포되면 CamelContext 에서 빈 인스턴스를 해결하기 위해 레지스트리 체인을 자동으로 설정합니다. 레지스트리 체인은 OSGi 레지스트리와 블루프린트(또는 Spring) 레지스트리로 구성됩니다.

2.4.4. Java에서 생성된 8080에 액세스

Java 8080(일반 이전 Java 오브젝트 또는 Cryostat)을 사용하여 교환 오브젝트를 처리하려면 Java 오브젝트의 메서드에 인바운드 교환을 바인딩하는 Cryostat () 프로세서를 사용합니다. 예를 들어, 클래스 MyBeanProcessor 를 사용하여 인바운드 교환을 처리하려면 다음과 같은 경로를 정의합니다.

from("file:data/inbound")
    .bean(MyBeanProcessor.class, "processBody")
    .to("file:data/outbound");

Cryostat () 프로세서는 MyBeanProcessor 유형의 인스턴스를 생성하고 processBody() 메서드를 호출하여 인바운드 교환을 처리합니다. 이 방법은 단일 경로에서 MyBeanProcessor 인스턴스에만 액세스하려는 경우에만 적합합니다. 그러나 여러 경로에서 동일한 MyBeanProcessor 인스턴스에 액세스하려면 Object 유형을 첫 번째 인수로 사용하는ans () 변형을 사용합니다. 예를 들면 다음과 같습니다.

MyBeanProcessor myBean = new MyBeanProcessor();

from("file:data/inbound")
    .bean(myBean, "processBody")
    .to("file:data/outbound");
from("activemq:inboundData")
    .bean(myBean, "processBody")
    .to("activemq:outboundData");

2.4.5. 과부하된 Cryostat 메서드에 액세스

Quarkus에서 오버로드된 메서드를 정의하는 경우 해당 매개 변수 유형과 함께 메서드 이름을 지정하여 호출할 오버로드된 메서드를 선택할 수 있습니다. 예를 들어 MyBeanBrocessor 클래스에 두 개의 오버로드된 메서드인 processBody(String)processBody(String,String) 가 있는 경우 다음과 같이 후자 오버로드된 메서드를 호출할 수 있습니다.

from("file:data/inbound")
  .bean(MyBeanProcessor.class, "processBody(String,String)")
  .to("file:data/outbound");

또는 각 매개변수의 유형을 명시적으로 지정하는 대신 사용하는 매개변수 수로 메서드를 식별하려면 와일드카드 문자 * 를 사용할 수 있습니다. 예를 들어 정확한 매개변수 유형에 관계없이 두 매개변수를 사용하는 processBody 라는 메서드를 호출하려면 다음과 같이 polkit () 프로세서를 호출합니다.

from("file:data/inbound")
.bean(MyBeanProcessor.class, "processBody(*,*)")
.to("file:data/outbound");

메서드를 지정할 때 간단한 정규화되지 않은 유형 이름(예: processBody(Exchange)) 또는 정규화된 유형 name(예: processBody(org.apache.camel.Exchange) 을 사용할 수 있습니다.

참고

현재 구현에서 지정된 유형 이름은 매개 변수 유형의 정확한 일치여야 합니다. 유형 상속은 고려되지 않습니다.

2.4.6. 매개변수를 명시적으로 지정

Quarkus 메서드를 호출할 때 매개 변수 값을 명시적으로 지정할 수 있습니다. 다음과 같은 간단한 유형 값을 전달할 수 있습니다.

  • 부울: true 또는 false.
  • 숫자: 123,7 등.
  • 문자열: ' 작은따옴표' 또는 "큰따옴표로".
  • null 개체: null.

다음 예제에서는 명시적 매개변수 값을 동일한 메서드 호출에서 형식 지정자와 혼합할 수 있는 방법을 보여줍니다.

from("file:data/inbound")
  .bean(MyBeanProcessor.class, "processBody(String, 'Sample string value', true, 7)")
  .to("file:data/outbound");

이전 예에서 첫 번째 매개변수의 값은 매개변수 바인딩 주석에 의해 결정될 수 있습니다( “기본 주석”참조).

간단한 유형 값 외에도 간단한 언어(30장. 간단한 언어)를 사용하여 매개변수 값을 지정할 수도 있습니다. 즉, 매개 변수 값을 지정할 때 Simple 언어의 전체 기능을 사용할 수 있습니다. 예를 들어 메시지 본문과 title 헤더의 값을 8080 메서드에 전달하려면 다음을 수행합니다.

from("file:data/inbound")
  .bean(MyBeanProcessor.class, "processBodyAndHeader(${body},${header.title})")
  .to("file:data/outbound");

전체 헤더 해시 맵을 매개변수로 전달할 수도 있습니다. 예를 들어 다음 예제에서는 두 번째 메서드 매개 변수를 java.util.Map 유형으로 선언해야 합니다.

from("file:data/inbound")
  .bean(MyBeanProcessor.class, "processBodyAndAllHeaders(${body},${header})")
  .to("file:data/outbound");
참고

Apache Camel 2.19 릴리스에서 빈 메서드 호출에서 null을 반환하는 경우 항상 메시지 본문이 null 값으로 설정되어 있는지 확인합니다.

2.4.7. 기본 방법 서명

빈 메서드에 교환을 바인딩하려면 특정 규칙을 준수하는 메서드 서명을 정의할 수 있습니다. 특히 메서드 서명에 대한 두 가지 기본 규칙이 있습니다.

2.4.8. 메시지 본문을 처리하기 위한 메서드 서명

들어오는 메시지 본문에 액세스하거나 수정하는 measure 메서드를 구현하려면 단일 문자열 인수를 사용하고 문자열 값을 반환하는 메서드 서명을 정의해야 합니다. 예를 들면 다음과 같습니다.

// Java
package com.acme;

public class MyBeanProcessor {
    public String processBody(String body) {
        // Do whatever you like to 'body'...
        return newBody;
    }
}

2.4.9. 교환 처리를 위한 방법 서명

유연성을 높이기 위해 들어오는 교환에 액세스하는 8080 방법을 구현할 수 있습니다. 이를 통해 모든 헤더, 본문 및 속성에 액세스하거나 수정할 수 있습니다. 교환 처리의 경우 메서드 서명은 단일 org.apache.camel.Exchange 매개 변수를 사용하고 void 를 반환합니다. 예를 들면 다음과 같습니다.

// Java
package com.acme;

public class MyBeanProcessor {
    public void processExchange(Exchange exchange) {
        // Do whatever you like to 'exchange'...
        exchange.getIn().setBody("Here is a new message body!");
    }
}

2.4.10. Spring XML에서 Spring 8080에 액세스

Java에서 빈 인스턴스를 생성하는 대신 Spring XML을 사용하여 인스턴스를 만들 수 있습니다. 실제로 XML로 경로를 정의하는 경우 가능한 유일한 접근 방식입니다. XML로 빈을 정의하려면 표준 Spring 8080 요소를 사용합니다. 다음 예제에서는 MyBeanProcessor 인스턴스를 만드는 방법을 보여줍니다.

<beans ...>
    ...
    <bean id="myBeanId" class="com.acme.MyBeanProcessor"/>
</beans>

Spring 구문을 사용하여 blank의 생성자 인수에 데이터를 전달할 수도 있습니다. Spring 8080 요소를 사용하는 방법에 대한 자세한 내용은 Spring 참조 가이드 의 IoC 컨테이너를 참조하십시오.

8080 요소를 사용하여 오브젝트 인스턴스를 생성할 때, 8080 요소의 id 속성 값(배터리의 ID 값)을 사용하여 나중에 참조할 수 있습니다. 예를 들어, myBeanId 와 동일한 ID가 있는 8080 요소가 있는 경우 다음과 같이 Cryostat Ref() 프로세서를 사용하여 Java DSL 경로의 빈 을 참조할 수 있습니다.

from("file:data/inbound").beanRef("myBeanId", "processBody").to("file:data/outbound");

여기서 Cryo statRef() 프로세서는 지정된 8080 인스턴스에서 MyBeanProcessor.processBody() 메서드를 호출합니다.

Camel 스키마의 8080 요소를 사용하여 Spring XML 경로 내에서 8080을 호출할 수도 있습니다. 예를 들면 다음과 같습니다.

<camelContext id="CamelContextID" xmlns="http://camel.apache.org/schema/spring">
  <route>
    <from uri="file:data/inbound"/>
    <bean ref="myBeanId" method="processBody"/>
    <to uri="file:data/outbound"/>
  </route>
</camelContext>

약간의 효율성 향상을 위해 cache 옵션을 true 로 설정하면 jenkins가 사용될 때마다 레지스트리를 조회하지 않도록 할 수 있습니다. 예를 들어 캐싱을 활성화하려면 다음과 같이 8080 요소에서 cache 특성을 설정할 수 있습니다.

<bean ref="myBeanId" method="processBody" cache="true"/>

2.4.11. Java에서 Spring 8080에 액세스

Spring 8080 요소를 사용하여 오브젝트 인스턴스를 생성할 때, 의 ID(Must 요소의 id 속성 값)를 사용하여 Java에서 개체 인스턴스를 참조할 수 있습니다. 예를 들어, myBeanId 와 동일한 ID가 있는 8080 요소가 있는 경우 다음과 같이 Cryostat Ref() 프로세서를 사용하여 Java DSL 경로의 빈 을 참조할 수 있습니다.

from("file:data/inbound").beanRef("myBeanId", "processBody").to("file:data/outbound");

또는 다음과 같이 @BeanInject 주석을 사용하여 삽입하여 Spring 8080을 참조할 수 있습니다.

// Java
import org.apache.camel.@BeanInject;
...
public class MyRouteBuilder extends RouteBuilder {

   @BeanInject("myBeanId")
   com.acme.MyBeanProcessor bean;

   public void configure() throws Exception {
     ..
   }
}

@BeanInject 주석에서 빈 ID를 생략하면 Camel에서 레지스트리를 유형별로 조회하지만 지정된 유형의 단일ans만 있는 경우에만 작동합니다. 예를 들어 com.acme.MyBeanProcessor 유형의ans를 조회하고 삽입하려면 다음을 수행합니다.

@BeanInject
com.acme.MyBeanProcessor bean;

2.4.12. Spring XML의 Cryostat 종료 순서

Camel 컨텍스트에서 사용하는 빈의 경우 일반적으로 올바른 종료 순서는 다음과 같습니다.

  1. camelContext 인스턴스를 종료하고 다음을 수행합니다.
  2. 사용된 빈을 종료합니다.

이 종료 순서가 역방향인 경우 Camel 컨텍스트가 이미 삭제되어 오류가 발생할 수 있습니다(오류로 직접 발생함). 또는 Camel 컨텍스트가 삭제되는 동안 누락된 Cryostat를 생성하려고 하면 오류도 발생할 수 있습니다. Spring XML의 기본 종료 순서는 빈과 camelContext 가 Spring XML 파일에 표시되는 순서에 따라 달라집니다. 잘못된 종료 순서로 인한 임의의 오류를 방지하기 위해 camelContext 는 Spring XML 파일의 다른 빈보다 먼저 종료되도록 구성됩니다. 이는 Apache Camel 2.13.0 이후의 기본 동작입니다.

이 동작을 변경해야 하는 경우( Camel 컨텍스트가 다른 빈보다 먼저 종료 되지 않도록 함) camelContext 요소에 shutdownEager 속성을 false 로 설정할 수 있습니다. 이 경우 Spring 종속 속성을 사용하여 종료 순서를 보다 세밀하게 제어할 수 있습니다.

2.4.13. 매개변수 바인딩 주석

“기본 방법 서명” 에 설명된 기본 매개변수 바인딩이 항상 사용하기에 편리하지는 않을 수 있습니다. 예를 들어 일부 데이터 조작을 수행하는 레거시 Java 클래스가 있는 경우 인바운드 교환에서 데이터를 추출하여 기존 메서드 서명의 인수에 매핑해야 할 수 있습니다. 이러한 종류의 매개변수 바인딩에 대해 Apache Camel은 다음과 같은 종류의 Java 주석을 제공합니다.

2.4.14. 기본 주석

표 2.3. “기본 Cryostat 주석” 메시지 데이터를 8080 메서드의 인수에 삽입하는 데 사용할 수 있는 org.apache.camel Java 패키지의 주석을 표시합니다.

표 2.3. 기본 Cryostat 주석

주석의미매개 변수?

@Attachments

첨부 파일 목록에 바인딩합니다.

 

@Body

인바운드 메시지 본문에 바인딩합니다.

 

@Header

인바운드 메시지 헤더에 바인딩합니다.

헤더의 문자열 이름입니다.

@Headers

인바운드 메시지 헤더의 java.util.Map 에 바인딩합니다.

 

@OutHeaders

아웃바운드 메시지 헤더의 java.util.Map 에 바인딩합니다.

 

@Property

이름이 지정된 교환 속성에 바인딩합니다.

속성의 문자열 이름입니다.

@Properties

교환 속성의 java.util.Map 에 바인딩합니다.

 

예를 들어 다음 클래스는 기본 주석을 사용하여 메시지 데이터를 processExchange() 메서드 인수에 삽입하는 방법을 보여줍니다.

// Java
import org.apache.camel.*;

public class MyBeanProcessor {
    public void processExchange(
        @Header(name="user") String user,
        @Body String body,
        Exchange exchange
    ) {
        // Do whatever you like to 'exchange'...
        exchange.getIn().setBody(body + "UserName = " + user);
    }
}

주석을 기본 규칙과 혼합하는 방법을 확인하십시오. 주석이 달린 인수를 삽입하는 것 외에도 매개 변수 바인딩은 교환 오브젝트를 org.apache.camel.Exchange 인수에 자동으로 삽입합니다.

2.4.15. 표현식 언어 주석

표현식 언어 주석은 message 데이터를 8080 메서드의 인수에 삽입하기 위한 강력한 메커니즘을 제공합니다. 이러한 주석을 사용하면 선택한 스크립팅 언어로 작성된 임의의 스크립트를 호출하여 인바운드 교환에서 데이터를 추출하고 메서드 인수에 데이터를 삽입할 수 있습니다. 표 2.4. “표현식 언어 주석” message 데이터를 Cryostat 메서드의 인수에 삽입하는 데 사용할 수 있는 org.apache.camel. Cryostat 패키지(및 비코어 주석의 하위 패키지)의 주석을 표시합니다.

표 2.4. 표현식 언어 주석

주석설명

@Bean

Cryostat 표현식을 삽입합니다.

@Constant

Constant 표현식을 삽입합니다.

@EL

EL 표현식을 삽입합니다.

@Groovy

Groovy 표현식을 삽입합니다.

@Header

헤더 표현식을 삽입합니다.

@JavaScript

JavaScript 표현식을 삽입합니다.

@OGNL

OGNL 표현식을 삽입합니다.

@PHP

PHP 표현식을 삽입합니다.

@Python

Python 표현식을 삽입합니다.

@Ruby

Ruby 표현식을 삽입합니다.

@Simple

단순 표현식을 삽입합니다.

@XPath

Cryostat 표현식을 삽입합니다.

@XQuery

XQuery 표현식을 삽입합니다.

예를 들어 다음 클래스는 @XPath 주석을 사용하여 들어오는 메시지의 본문에서 사용자 이름과 암호를 XML 형식으로 추출하는 방법을 보여줍니다.

// Java
import org.apache.camel.language.*;

public class MyBeanProcessor {
    public void checkCredentials(
        @XPath("/credentials/username/text()") String user,
        @XPath("/credentials/password/text()") String pass
    ) {
        // Check the user/pass credentials...
        ...
    }
}

@Bean 주석은 등록된 8080을 호출한 결과를 삽입할 수 있기 때문에 특별한 경우입니다. 예를 들어 메서드 인수에 상관 관계 ID를 삽입하려면 @Bean 주석을 사용하여 다음과 같이 ID 생성기 클래스를 호출할 수 있습니다.

// Java
import org.apache.camel.language.*;

public class MyBeanProcessor {
    public void processCorrelatedMsg(
        @Bean("myCorrIdGenerator") String corrId,
        @Body String body
    ) {
        // Check the user/pass credentials...
        ...
    }
}

여기서 myCorrIdGenerator 문자열은 ID 생성기 인스턴스의 빈 ID입니다. ID 생성기 클래스는 다음과 같이 spring 8080 요소를 사용하여 인스턴스화할 수 있습니다.

<beans ...>
    ...
    <bean id="myCorrIdGenerator" class="com.acme.MyIdGenerator"/>
</beans>

여기에서 MyIdGenerator 클래스를 다음과 같이 정의할 수 있습니다.

// Java
package com.acme;

public class MyIdGenerator {

    private UserManager userManager;

    public String generate(
        @Header(name = "user") String user,
        @Body String payload
    ) throws Exception {
       User user = userManager.lookupUser(user);
       String userId = user.getPrimaryId();
       String id = userId + generateHashCodeForPayload(payload);
       return id;
   }
}

참조된 8080 클래스 MyIdGenerator 에서 주석을 사용할 수도 있습니다. generate() 메서드 서명에 대한 유일한 제한 사항은 @Bean 에서 주석이 달린 인수에 삽입하려면 올바른 유형을 반환해야 한다는 것입니다. @Bean 주석은 메서드 이름을 지정할 수 없으므로 주입 메커니즘은 일치하는 반환 유형이 있는 참조 빈에서 첫 번째 메서드를 호출하기만 하면 됩니다.

참고

일부 언어 주석은 코어 구성 요소(@Bean,@Constant,@Simple, @XPath)에서 사용할 수 있습니다. 그러나 코어가 아닌 구성 요소의 경우 관련 구성 요소를 로드해야 합니다. 예를 들어 OGNL 스크립트를 사용하려면 camel-ognl 구성 요소를 로드해야 합니다.

2.4.16. 상속된 주석

매개변수 바인딩 주석은 인터페이스 또는 슈퍼클래스에서 상속될 수 있습니다. 예를 들어 Header 주석과 Body 주석을 사용하여 Java 인터페이스를 정의하는 경우 다음과 같이 다음과 같습니다.

// Java
import org.apache.camel.*;

public interface MyBeanProcessorIntf {
    void processExchange(
        @Header(name="user") String user,
        @Body String body,
        Exchange exchange
    );
}

구현 클래스에 정의된 오버로드된 메서드 MyBeanProcessor 는 다음과 같이 기본 인터페이스에 정의된 주석을 상속합니다.

// Java
import org.apache.camel.*;

public class MyBeanProcessor implements MyBeanProcessorIntf {
    public void processExchange(
        String user,  // Inherits Header annotation
        String body,  // Inherits Body annotation
        Exchange exchange
    ) {
        ...
    }
}

2.4.17. 인터페이스 구현

Java 인터페이스를 구현하는 클래스는 종종개인 또는 패키지 전용 범위로 보호됩니다. 이러한 방식으로 제한된 구현 클래스에서 메서드를 호출하려고 하면 Quarkus 바인딩이 공개적으로 액세스할 수 있는 해당 인터페이스 메서드를 호출하는 것으로 대체됩니다.

예를 들어 다음 공용 Cryostat Intf 인터페이스를 고려해 보십시오.

// Java
public interface BeanIntf {
    void processBodyAndHeader(String body, String title);
}

여기서 Cryo statIntf 인터페이스는 다음 보호된 Cryostat IntfImpl 클래스에 의해 구현됩니다.

// Java
protected class BeanIntfImpl implements BeanIntf {
    void processBodyAndHeader(String body, String title) {
        ...
    }
}

다음 Cryostat 호출은 public Cryostat Intf.processBodyAndHeader 메서드를 호출합니다.

from("file:data/inbound")
  .bean(BeanIntfImpl.class, "processBodyAndHeader(${body}, ${header.title})")
  .to("file:data/outbound");

2.4.18. 정적 메서드 호출

Cryostat 통합에는 연결된 클래스의 인스턴스를 생성하지 않고도 정적 메서드를 호출할 수 있습니다. 예를 들어 정적 메서드를 정의하는 다음 Java 클래스를, changeSomething():

// Java
...
public final class MyStaticClass {
    private MyStaticClass() {
    }

    public static String changeSomething(String s) {
        if ("Hello World".equals(s)) {
            return "Bye World";
        }
        return null;
    }

    public void doSomething() {
        // noop
    }
}

polkit 통합을 사용하여 다음과 같이 정적 변경Something 메서드를 호출할 수 있습니다.

from("direct:a")
  *.bean(MyStaticClass.class, "changeSomething")*
  .to("mock:a");

이 구문은 일반 함수의 호출과 동일하지만, 8080 통합은 Java 리플렉션을 악용하여 메서드를 정적으로 식별하고 MyStaticClass 를 인스턴스화 하지 않고 메서드를 호출합니다.

2.4.19. OSGi 서비스 호출

Red Hat Fuse 컨테이너에 경로가 배포되는 특수한 경우 metrics 통합을 사용하여 OSGi 서비스를 직접 호출할 수 있습니다. 예를 들어 OSGi 컨테이너의 번들 중 하나가 서비스를 내보냈다고 가정하면 org.fusesource.example.HelloWorldOsgiService.NET Framework 통합 코드를 사용하여 sayHello 메서드를 호출할 수 있습니다.

from("file:data/inbound")
  .bean(org.fusesource.example.HelloWorldOsgiService.class, "sayHello")
  .to("file:data/outbound");

다음과 같이 Quarkus 구성 요소를 사용하여 Spring 또는 블루프린트 XML 파일 내에서 OSGi 서비스를 호출할 수도 있습니다.

<to uri="bean:org.fusesource.example.HelloWorldOsgiService?method=sayHello"/>

이 작동 방식은 Apache Camel이 OSGi 컨테이너에 배포될 때 레지스트리 체인을 설정하는 것입니다. 먼저 OSGi 서비스 레지스트리에서 지정된 클래스 이름을 조회합니다. 이 조회가 실패하면 로컬 Spring DM 또는 블루프린트 레지스트리로 대체됩니다.

2.5. 교환 인스턴스 생성

2.5.1. 개요

Java 코드를 사용하여 메시지를 처리할 때(예: Quarkus 클래스 또는 프로세서 클래스에서) 새 교환 인스턴스를 생성해야 하는 경우가 많습니다. Exchange 개체를 만들어야 하는 경우 여기에 설명된 대로 가장 쉬운 방법은 ExchangeBuilder 클래스의 메서드를 호출하는 것입니다.

2.5.2. ExchangeBuilder 클래스

ExchangeBuilder 클래스의 정규화된 이름은 다음과 같습니다.

org.apache.camel.builder.ExchangeBuilder

ExchangeBuilder 는 exchange 개체 빌드 를 시작하는 데 사용할 수 있는Exchange 를 통해 정적 메서드를 노출합니다.

2.5.3. 예제

예를 들어 다음 코드는 메시지 본문 문자열, Hello World!, 사용자 이름 및 암호 인증 정보가 포함된 헤더를 포함하는 새 교환 오브젝트를 생성합니다.

// Java
import org.apache.camel.Exchange;
import org.apache.camel.builder.ExchangeBuilder;
...
Exchange exch = ExchangeBuilder.anExchange(camelCtx)
                    .withBody("Hello World!")
                    .withHeader("username", "jdoe")
                    .withHeader("password", "pass")
                    .build();

2.5.4. ExchangeBuilder 방법

ExchangeBuilder 클래스는 다음 메서드를 지원합니다.

ExchangeBuilder anExchange(CamelContext 컨텍스트)
(static 메서드) 교환 오브젝트를 빌드합니다.
Exchange build()
교환을 빌드합니다.
ExchangeBuilder withBody(오브젝트 본문)
교환에 메시지 본문을 설정합니다(즉, 교환의 메시지 본문을 설정).
Header(문자열 키, 오브젝트 값)를 사용한 ExchangeBuilder
교환에 헤더를 설정합니다(즉, 교환의 In 메시지에 헤더를 설정).
ExchangeBuilder withPattern(ExchangePattern 패턴)
교환에 대한 교환 패턴을 설정합니다.
ExchangeBuilder withProperty(문자열 키, 오브젝트 값)
교환에 속성을 설정합니다.

2.6. 메시지 콘텐츠 변환

초록

Apache Camel은 메시지 콘텐츠를 변환하는 다양한 방법을 지원합니다. Apache Camel은 메시지 콘텐츠를 수정하기 위한 간단한 기본 API 외에도 다양한 타사 라이브러리 및 변환 표준과의 통합을 지원합니다.

2.6.1. 간단한 메시지입니다.

2.6.1.1. 개요

Java DSL에는 수신 및 발신 메시지에 대해 간단한 변환을 수행할 수 있는 기본 제공 API가 있습니다. 예를 들어 예 2.1. “Incoming Messages” 에 표시된 규칙은 들어오는 메시지 본문의 끝에 텍스트 World! 를 추가합니다.

예 2.1. Incoming Messages

from("SourceURL").setBody(body().append(" World!")).to("TargetURL");

여기서 setBody() 명령은 들어오는 메시지 본문의 내용을 대체합니다.

2.6.1.2. 간단한 변환을 위한 API

다음 API 클래스를 사용하여 라우터 규칙에서 메시지 콘텐츠를 간단한 변환을 수행할 수 있습니다.

  • org.apache.camel.model.ProcessorDefinition
  • org.apache.camel.builder.Builder
  • org.apache.camel.builder.ValueBuilder

2.6.1.3. ProcessorDefinition 클래스

org.apache.camel.model.ProcessorDefinition 클래스는 예 2.1. “Incoming Messages”setBody() 명령에 직접 삽입할 수 있는 DSL 명령을 정의합니다. 표 2.5. “ProcessorDefinition 클래스의 transformation Methods” 메시지 콘텐츠 변환과 관련된 ProcessorDefinition 메서드를 표시합니다.

표 2.5. ProcessorDefinition 클래스의 transformation Methods

방법설명

type convertBodyTo(Class 유형)

IN 메시지 본문을 지정된 형식으로 변환합니다.

type removeFaultHeader(String name)

CryostatULT 메시지에서 헤더를 제거하는 프로세서를 추가합니다.

type removeHeader(문자열 이름)

IN 메시지에서 헤더를 제거하는 프로세서를 추가합니다.

type removeProperty(문자열 이름)

교환 속성을 제거하는 프로세서를 추가합니다.

ExpressionClause<ProcessorDefinition<Type>> setBody()

IN 메시지에 본문을 설정하는 프로세서를 추가합니다.

setFaultBody(Expression expression)를 입력합니다.

vmULT 메시지에 본문을 설정하는 프로세서를 추가합니다.

setFaultHeader(문자열 이름, 표현식)을 입력합니다.

CryostatULT 메시지에 헤더를 설정하는 프로세서를 추가합니다.

ExpressionClause<ProcessorDefinition<Type>> setHeader(String name)

IN 메시지에 헤더를 설정하는 프로세서를 추가합니다.

setHeader(문자열 이름, 표현식)를 입력합니다.

IN 메시지에 헤더를 설정하는 프로세서를 추가합니다.

ExpressionClause<ProcessorDefinition<Type>> setOutHeader(String name)

OUT 메시지에 헤더를 설정하는 프로세서를 추가합니다.

setOutHeader(문자열 이름, 표현식)를 입력합니다.

OUT 메시지에 헤더를 설정하는 프로세서를 추가합니다.

ExpressionClause<ProcessorDefinition<Type>> setProperty(String name)

교환 속성을 설정하는 프로세서를 추가합니다.

setProperty(문자열 이름, 표현식)를 입력합니다.

교환 속성을 설정하는 프로세서를 추가합니다.

ExpressionClause<ProcessorDefinition<Type>> transform()

OUT 메시지에 본문을 설정하는 프로세서를 추가합니다.

type transform(Expression expression)

OUT 메시지에 본문을 설정하는 프로세서를 추가합니다.

2.6.1.4. 빌더 클래스

org.apache.camel.builder.Builder 클래스는 표현식 또는 서술자가 예상되는 컨텍스트의 메시지 콘텐츠에 대한 액세스를 제공합니다. 즉, 빌더 메서드는 일반적으로 DSL 명령의 인수 에서 호출됩니다(예: 예 2.1. “Incoming Messages”body() 명령). 표 2.6. “빌더 클래스의 메서드” Builder 클래스에서 사용할 수 있는 정적 메서드를 요약합니다.

표 2.6. 빌더 클래스의 메서드

방법설명

static <E extends Exchange> ValueBuilder<E> body()

교환에서 인바운드 본문에 대한 서술자 및 값 빌더를 반환합니다.

static <E extends Exchange,T> ValueBuilder<E> bodyAs(Class<T> 유형)

인바운드 메시지 본문에 대한 서술자 및 값 빌더를 특정 유형으로 반환합니다.

static <E extends Exchange> ValueBuilder<E> constant(Object value)

상수 표현식을 반환합니다.

static <E extends Exchange> ValueBuilder<E> faultBody()

교환에서 fault 본문에 대한 서술자 및 값 빌더를 반환합니다.

static <E extends Exchange,T> ValueBuilder<E> faultBodyAs(Class<T> 유형)

fault 메시지 본문에 대한 서술자 및 값 빌더를 특정 유형으로 반환합니다.

static <E extends Exchange> ValueBuilder<E> header(String name)

교환의 헤더에 대한 서술자 및 값 빌더를 반환합니다.

static <E extends Exchange> ValueBuilder<E> outBody()

교환에서 아웃바운드 본문에 대한 서술자 및 값 빌더를 반환합니다.

static <E extends Exchange> ValueBuilder<E> outBodyAs(Class<T> 유형)

아웃바운드 메시지 본문의 서술자 및 값 빌더를 특정 유형으로 반환합니다.

정적 ValueBuilder 속성(문자열 이름)

교환의 속성에 대한 서술자 및 값 빌더를 반환합니다.

static ValueBuilder regexReplaceAll(Expression 콘텐츠, 문자열 regex, Expression 대체)

정규식을 모두 지정된 교체로 대체하는 표현식을 반환합니다.

static ValueBuilder regexReplaceAll(Expression 콘텐츠, 문자열 regex, 문자열 대체)

정규식을 모두 지정된 교체로 대체하는 표현식을 반환합니다.

static ValueBuilder sendTo(String uri)

지정된 엔드포인트 uri로 교환을 보내는 표현식을 반환합니다.

static <E extends Exchange> ValueBuilder<E> systemProperty(String name)

지정된 시스템 속성에 대한 표현식을 반환합니다.

static <E extends Exchange> ValueBuilder<E> systemProperty(String name, String defaultValue)

지정된 시스템 속성에 대한 표현식을 반환합니다.

2.6.1.5. ValueBuilder 클래스

org.apache.camel.builder.ValueBuilder 클래스를 사용하면 Builder 메서드에서 반환된 값을 수정할 수 있습니다. 즉 ValueBuilder의 메서드는 메시지 내용을 수정하는 간단한 방법을 제공합니다.In other words, the methods in ValueBuilder provide a simple way of modifying message content. 표 2.7. “ValueBuilder 클래스의 한정자 메서드” ValueBuilder 클래스에서 사용할 수 있는 메서드를 요약합니다. 즉, 테이블에 호출되는 값을 수정하는 데 사용되는 메서드만 표시됩니다(자세한 내용은 API 참조 문서 참조 참조 ).

표 2.7. ValueBuilder 클래스의 한정자 메서드

방법설명

ValueBuilder<E> append(Object value)

지정된 값으로 이 표현식의 문자열 평가를 추가합니다.

서술자는(Object value)를 포함합니다.

왼쪽 표현식에 오른쪽 표현식의 값이 포함된 서술자를 생성합니다.

ValueBuilder<E> convertTo(Class 유형)

등록된 형식 변환기를 사용하여 현재 값을 지정된 형식으로 변환합니다.Converts the current value to the given type using the registered type converters.

ValueBuilder<E> convertToString()

등록된 형식 변환기를 사용하여 문자열을 변환합니다.Converts a string using the registered type converters.

서술자 endWith(Object 값)

 

<t> T evaluate (Exchange exchange, Class<T> type)

 

서술자(Object…​ 값)

 

서술자(Predicate…​ 서술자)

 

predicate isEqualTo(Object value)

현재 값이 지정된 value 인수와 같은 경우 true를 반환합니다.

predicate isGreaterThan(Object value)

현재 값이 지정된 value 인수보다 큰 경우 true를 반환합니다.

predicate isGreaterThanOrEqualTo(Object 값)

현재 값이 지정된 value 인수보다 크거나 같은 경우 true를 반환합니다.

서술자 isInstanceOf(Class 유형)

현재 값이 지정된 형식의 인스턴스인 경우 true를 반환합니다.

predicate isLessThan(Object value)

현재 값이 지정된 value 인수보다 작은 경우 true를 반환합니다.

predicate isLessThanOrEqualTo(Object value)

현재 값이 지정된 value 인수보다 작거나 같은 경우 true를 반환합니다.

predicate isNotEqualTo(Object value)

현재 값이 지정된 value 인수와 같지 않은 경우 true를 반환합니다.

Predicate isNotNull()

현재 값이 null 이 아닌 경우 true를 반환합니다.

Predicate isNull()

현재 값이 null 인 경우 true를 반환합니다.

서술자 일치(Expression 표현식)

 

서술자 not(Predicate 서술자)

서술자 인수를 부정합니다.

ValueBuilder prepend(Object value)

이 표현식의 문자열 평가 앞에 지정된 값에 추가합니다.

predicate regex(문자열 regex)

 

ValueBuilder<E> regexReplaceAll(String regex, Expression<E> replacement)

정규 표현식의 모든 occurrencies를 지정된 교체로 대체합니다.

ValueBuilder<E> regexReplaceAll(String regex, String replacement)

정규 표현식의 모든 occurrencies를 지정된 교체로 대체합니다.

ValueBuilder<E> regexTokenize(String regex)

지정된 정규식을 사용하여 이 표현식의 문자열 변환을 토큰화합니다.

ValueBuilder sort(Comparator 비교자)

지정된 비교기를 사용하여 현재 값을 정렬합니다.

서술자 startsWith(Object 값)

현재 값이 value 인수의 문자열 값과 일치하는 경우 true를 반환합니다.

ValueBuilder<E> tokenize()

쉼표 토큰 구분자를 사용하여 이 표현식의 문자열 변환을 토큰화합니다.

ValueBuilder<E> 토큰화(문자열 토큰)

지정된 토큰 구분자를 사용하여 이 표현식의 문자열 변환을 토큰화합니다.

2.6.2. 마샬링 및 Unmarshalling

2.6.2.1. Java DSL 명령

다음 명령을 사용하여 하위 수준 및 높은 수준의 메시지 형식을 변환할 수 있습니다.

  • Marshal() Cryostat- Cryostat 높은 수준의 데이터 형식을 낮은 수준의 데이터 형식으로 변환합니다.
  • unmarshal() Cryostat-6.1은 낮은 수준의 데이터 형식을 높은 수준의 데이터 형식으로 변환합니다.

2.6.2.2. 데이터 형식

Apache Camel은 다음 데이터 형식을 마샬링 및 unmarshalling하도록 지원합니다.

  • Java serialization
  • JAXB
  • XMLBeans
  • XStream

2.6.2.3. Java serialization

Java 개체를 바이너리 데이터의 Blob으로 변환할 수 있습니다. 이 데이터 형식의 경우 unmarshalling은 바이너리 Blob을 Java 개체로 변환하고 마샬링은 Java 개체를 바이너리 Blob으로 변환합니다. 예를 들어 끝점인 SourceURL 에서 직렬화된 Java 오브젝트를 읽고 Java 오브젝트로 변환하려면 다음과 같은 규칙을 사용합니다.

from("SourceURL").unmarshal().serialization()
.<FurtherProcessing>.to("TargetURL");

또는 Spring XML:

<camelContext id="serialization" xmlns="http://camel.apache.org/schema/spring">
  <route>
    <from uri="SourceURL"/>
    <unmarshal>
      <serialization/>
    </unmarshal>
    <to uri="TargetURL"/>
  </route>
</camelContext>

2.6.2.4. JAXB

XML 스키마 유형과 Java 유형 간의 매핑을 제공합니다( https://jaxb.dev.java.net/참조). CryostatB의 경우 unmarshalling은 XML 데이터 형식을 Java 개체로 변환하고 마샬링은 Java 개체를 XML 데이터 형식으로 변환합니다. CryostatB 데이터 형식을 사용하려면 먼저 schema의 XML 데이터 형식을 나타내는 Java 클래스를 생성하려면 XML 스키마를 컴파일해야 합니다. 이를 스키마 바인딩 이라고 합니다. 스키마가 바인딩된 후 다음과 같은 코드를 사용하여 Java 오브젝트에 XML 데이터를 unmarshal하는 규칙을 정의합니다.

org.apache.camel.spi.DataFormat jaxb = new org.apache.camel.converter.jaxb.JaxbDataFormat("GeneratedPackageName");

from("SourceURL").unmarshal(jaxb)
.<FurtherProcessing>.to("TargetURL");

여기서 GeneratedPackagename 은 XML 스키마를 나타내는 Java 클래스를 포함하는 CryostatB 컴파일러에서 생성한 Java 패키지의 이름입니다.

또는 Spring XML:

<camelContext id="jaxb" xmlns="http://camel.apache.org/schema/spring">
  <route>
    <from uri="SourceURL"/>
    <unmarshal>
      <jaxb prettyPrint="true" contextPath="GeneratedPackageName"/>
    </unmarshal>
    <to uri="TargetURL"/>
  </route>
</camelContext>

2.6.2.5. XMLBeans

XML 스키마 유형과 Java 유형 간의 대체 매핑을 제공합니다( http://xmlbeans.apache.org/참조). XMLBeans의 경우 unmarshalling은 XML 데이터 형식을 Java 개체로 변환하고 마샬링은 Java 개체를 XML 데이터 형식으로 변환합니다. 예를 들어 XMLBeans를 사용하여 Java 오브젝트에 XML 데이터를 unmarshal하려면 다음과 같은 코드를 사용합니다.

from("SourceURL").unmarshal().xmlBeans()
.<FurtherProcessing>.to("TargetURL");

또는 Spring XML:

<camelContext id="xmlBeans" xmlns="http://camel.apache.org/schema/spring">
  <route>
    <from uri="SourceURL"/>
    <unmarshal>
      <xmlBeans prettyPrint="true"/>
    </unmarshal>
    <to uri="TargetURL"/>
  </route>
</camelContext>

2.6.2.6. XStream

XML 유형과 Java 유형 간의 다른 매핑을 제공합니다( http://www.xml.com/pub/a/2004/08/18/xstream.html참조). XStream은 Java 직렬화와 같은 직렬화 라이브러리이므로 Java 개체를 XML로 변환할 수 있습니다. XStream의 경우 unmarshalling은 XML 데이터 형식을 Java 개체로 변환하고 마샬링은 Java 개체를 XML 데이터 형식으로 변환합니다.

from("SourceURL").unmarshal().xstream()
.<FurtherProcessing>.to("TargetURL");
참고

XStream 데이터 형식은 현재 Spring XML에서 지원되지 않습니다.

2.6.3. 끝점 바인딩

2.6.3.1. 바인딩이란 무엇입니까?

Apache Camel에서 바인딩 은 데이터 형식, 콘텐츠 Enricher 또는 검증 단계를 적용하여 계약 내 엔드포인트를 래핑하는 방법입니다. 상태 또는 변환은 들어오는 메시지에 적용되며 보완적인 조건 또는 변환이 표시되는 메시지에 적용됩니다.

2.6.3.2. DataFormatBinding

DataFormatBinding 클래스는 특정 데이터 형식을 마샬링하고 unmarshalshal하는 바인딩을 정의하려는 특정 사례에 유용합니다( 2.6.2절. “마샬링 및 Unmarshalling”참조). 이 경우 바인딩을 생성하는 데 필요한 모든 작업은 DataFormatBinding 인스턴스를 생성하고 생성자에서 관련 데이터 형식에 참조를 전달하는 것입니다.

예를 들어 예 2.2. “CryostatB 바인딩” 의 XML DSL 스니펫에는 Apache Camel 끝점과 연결된 경우 CryostatB 데이터 형식을 마샬링하고 분리할 수 있는 바인딩(ID, jaxb)이 표시됩니다.

예 2.2. CryostatB 바인딩

<beans ... >
    ...
    <bean id="jaxb" class="org.apache.camel.processor.binding.DataFormatBinding">
        <constructor-arg ref="jaxbformat"/>
    </bean>

    <bean id="jaxbformat" class="org.apache.camel.model.dataformat.JaxbDataFormat">
        <property name="prettyPrint" value="true"/>
        <property name="contextPath" value="org.apache.camel.example"/>
    </bean>

</beans>

2.6.3.3. 바인딩과 끝점 연결

다음 대안은 바인딩을 끝점과 연결하는 데 사용할 수 있습니다.

2.6.3.4. 바인딩 URI

바인딩을 끝점과 연결하려면 엔드포인트 URI를 바인딩:NameOfBinding 로 접두사로 지정할 수 있습니다. 여기서 NameOfBinding 은 바인딩의 빈 ID입니다(예: Spring XML에서 생성된 바인딩 빈의 ID).

예를 들어 다음 예제에서는 ActiveMQ 끝점을 예 2.2. “CryostatB 바인딩” 에 정의된 CryostatB 바인딩과 연결하는 방법을 보여줍니다.

<beans ...>
    ...
    <camelContext xmlns="http://camel.apache.org/schema/spring">
        <route>
            <from uri="binding:jaxb:activemq:orderQueue"/>
            <to uri="binding:jaxb:activemq:otherQueue"/>
        </route>
    </camelContext>
    ...
</beans>

2.6.3.5. BindingComponent

접두사를 사용하여 엔드포인트와 바인딩을 연결하는 대신, 바인딩을 URI에 표시할 필요가 없도록 연결을 암시적으로 만들 수 있습니다. 암시적 바인딩이 없는 기존 끝점의 경우 가장 쉬운 방법은 BindingComponent 클래스를 사용하여 끝점을 래핑하는 것입니다.

예를 들어 jaxb 바인딩을 activemq 엔드포인트와 연결하려면 다음과 같이 새 BindingComponent 인스턴스를 정의할 수 있습니다.

<beans ... >
    ...
    <bean id="jaxbmq" class="org.apache.camel.component.binding.BindingComponent">
        <constructor-arg ref="jaxb"/>
        <constructor-arg value="activemq:foo."/>
    </bean>

    <bean id="jaxb" class="org.apache.camel.processor.binding.DataFormatBinding">
        <constructor-arg ref="jaxbformat"/>
    </bean>

    <bean id="jaxbformat" class="org.apache.camel.model.dataformat.JaxbDataFormat">
        <property name="prettyPrint" value="true"/>
        <property name="contextPath" value="org.apache.camel.example"/>
    </bean>

</beans>

여기서 (선택 사항) jaxbmq 의 두 번째 생성자 인수는 URI 접두사를 정의합니다. 이제 엔드포인트 URI의 스키마로 jaxbmq ID를 사용할 수 있습니다. 예를 들어 이 바인딩 구성 요소를 사용하여 다음 경로를 정의할 수 있습니다.

<beans ...>
    ...
    <camelContext xmlns="http://camel.apache.org/schema/spring">
        <route>
            <from uri="jaxbmq:firstQueue"/>
            <to uri="jaxbmq:otherQueue"/>
        </route>
    </camelContext>
    ...
</beans>

이전 경로는 바인딩 URI 접근 방식을 사용하는 다음 경로와 동일합니다.

<beans ...>
    ...
    <camelContext xmlns="http://camel.apache.org/schema/spring">
        <route>
            <from uri="binding:jaxb:activemq:foo.firstQueue"/>
            <to uri="binding:jaxb:activemq:foo.otherQueue"/>
        </route>
    </camelContext>
    ...
</beans>
참고

사용자 지정 Apache Camel 구성 요소를 구현하는 개발자의 경우 org.apache.camel.spi.HasBinding 인터페이스에서 상속하는 엔드포인트 클래스를 구현하여 이 작업을 수행할 수 있습니다.

2.6.3.6. BindingComponent 생성자

BindingComponent 클래스는 다음 생성자를 지원합니다.

public BindingComponent()
인수 양식이 없습니다. 속성 주입을 사용하여 바인딩 구성 요소 인스턴스를 구성합니다.
public BindingComponent(Binding binding)
이 바인딩 구성 요소를 지정된 Binding 개체, 바인딩 과 연결합니다.
public BindingComponent(Binding binding, String uriPrefix)
이 바인딩 구성 요소를 지정된 Binding 오브젝트, 바인딩 및 URI 접두사인 uriPrefix 와 연결합니다. 가장 일반적으로 사용되는 생성자입니다.
public BindingComponent(Binding binding, String uriPrefix, String uriPostfix)
이 생성자는 이 바인딩 구성 요소를 사용하여 정의된 모든 URI에 자동으로 추가되는 uriPostfix, 인수 등 추가 URI를 지원합니다.

2.6.3.7. 사용자 정의 바인딩 구현

데이터 형식을 마샬링 및 unmarshalling하는 데 사용되는 DataFormatBinding 외에도 자체 사용자 지정 바인딩을 구현할 수 있습니다.In addition to the DataFormatBinding , which is used for marshalling and unmarshalling data formats, you can implement your own custom bindings. 다음과 같이 사용자 정의 바인딩을 정의합니다.

  1. org.apache.camel.Processor 클래스를 구현하여 소비자 엔드포인트에 들어오는 메시지에서 변환을 수행합니다( from 요소에서 표시).
  2. 상호 보완적인 org.apache.camel.Processor 클래스를 구현하여 생산자 엔드포인트에서 나가는 메시지(에 대한 요소)에서 역방향 변환을 수행합니다.
  3. 프로세서 인스턴스의 팩토리 역할을 하는 org.apache.camel.spi.Binding 인터페이스를 구현합니다.

2.6.3.8. 바인딩 인터페이스

예 2.3. “org.apache.camel.spi.Binding 인터페이스” 사용자 지정 바인딩을 정의하기 위해 구현해야 하는 org.apache.camel.spi.Binding 인터페이스의 정의를 표시합니다.

예 2.3. org.apache.camel.spi.Binding 인터페이스

// Java
package org.apache.camel.spi;

import org.apache.camel.Processor;

/**
 * Represents a <a href="http://camel.apache.org/binding.html">Binding</a> or contract
 * which can be applied to an Endpoint; such as ensuring that a particular
 * <a href="http://camel.apache.org/data-format.html">Data Format</a> is used on messages in and out of an endpoint.
 */
public interface Binding {

    /**
     * Returns a new {@link Processor} which is used by a producer on an endpoint to implement
     * the producer side binding before the message is sent to the underlying endpoint.
     */
    Processor createProduceProcessor();

    /**
     * Returns a new {@link Processor} which is used by a consumer on an endpoint to process the
     * message with the binding before its passed to the endpoint consumer producer.
     */
    Processor createConsumeProcessor();
}

2.6.3.9. 바인딩을 사용해야 하는 경우

바인딩은 동일한 종류의 변환을 여러 종류의 엔드포인트에 적용해야 하는 경우에 유용합니다.

2.7. 자산 위치 소유자

2.7.1. 개요

속성 자리 표시자 기능을 사용하여 문자열을 다양한 컨텍스트(예: XML DSL 요소의 끝점 URI 및 속성)로 대체할 수 있습니다. 자리 표시자 설정은 Java 속성 파일에 저장됩니다. 이 기능은 다양한 Apache Camel 애플리케이션 간에 설정을 공유하거나 특정 구성 설정을 중앙 집중화하려는 경우 유용할 수 있습니다.

예를 들어 다음 경로는 호스트와 포트가 자리 표시자인 {{remote.host}} 및 {{remote.port}} 로 대체되는 웹 서버에 요청을 보냅니다.

from("direct:start").to("http://{{remote.host}}:{{remote.port}}");

자리 표시자 값은 다음과 같이 Java 속성 파일에서 정의됩니다.

# Java properties file
remote.host=myserver.com
remote.port=8080
참고

속성 위치 소유자는 UTF-8과 같은 특정 문자 세트를 사용하여 .properties 파일을 읽을 수 있는 인코딩 옵션을 지원합니다. 그러나 기본적으로 ISO-8859-1 문자 세트를 구현합니다.

PropertyPlaceholders 를 사용하는 Apache Camel은 다음을 지원합니다.

  • 조회할 키와 함께 기본값을 지정합니다.
  • 모든 자리 표시자 키가 사용할 기본값으로 구성된 경우 PropertiesComponent 를 정의할 필요가 없습니다.
  • 타사 함수를 사용하여 속성 값을 조회합니다. 자체 논리를 구현할 수 있습니다.

    참고

    OS 환경 변수, JVM 시스템 속성 또는 서비스 이름 idiom에서 값을 조회할 수 있는 상자 함수 3개를 제공합니다.

2.7.2. 속성 파일

속성 설정은 하나 이상의 Java 속성 파일에 저장되며 표준 Java 속성 파일 형식을 준수해야 합니다. 각 속성 설정은 Key=Value 형식으로 자체 줄에 표시됩니다. 비어 있지 않은 첫 번째 문자가 있는 줄은 주석으로 처리됩니다.

예를 들어, 속성 파일에는 예 2.4. “속성 파일 샘플” 에 표시된 대로 콘텐츠가 있을 수 있습니다.

예 2.4. 속성 파일 샘플

# Property placeholder settings
# (in Java properties file format)
cool.end=mock:result
cool.result=result
cool.concat=mock:{{cool.result}}
cool.start=direct:cool
cool.showid=true

cheese.end=mock:cheese
cheese.quote=Camel rocks
cheese.type=Gouda

bean.foo=foo
bean.bar=bar

2.7.3. 속성 해결

속성 구성 요소는 경로 정의에서 사용하기 전에 하나 이상의 속성 파일의 위치로 구성해야 합니다. 다음 해결 방법 중 하나를 사용하여 속성 값을 제공해야 합니다.

classpath:PathName,PathName,…​
(default) classpath의 위치를 지정합니다. 여기서 PathName 은 슬래시를 사용하여 구분된 파일 경로 이름입니다.
파일:PathName,PathName,…​
파일 시스템의 위치를 지정합니다. 여기서 PathName 은 슬래시를 사용하여 구분된 파일 경로 이름입니다.
ref: CryostatID
레지스트리에서 java.util.Properties 오브젝트의 ID를 지정합니다.
블루프린트: CryostatID
OSGi 구성 관리 서비스에 정의된 속성에 액세스하기 위해 OSGi 블루프린트 파일의 컨텍스트에서 사용되는 cm:property-placeholder hieradata의 ID를 지정합니다. 자세한 내용은 “OSGi 블루프린트 속성 자리 표시자와 통합”의 내용을 참조하십시오.

예를 들어, classpath에 있는 com/fusesource/cheese.properties 속성 파일과 com/fusesource/bar.properties 속성 파일을 지정하려면 다음 위치 문자열을 사용합니다.

com/fusesource/cheese.properties,com/fusesource/bar.properties
참고

classpath 확인자가 기본적으로 사용되므로 이 예제에서 classpath: 접두사를 생략할 수 있습니다.

2.7.4. 시스템 속성 및 환경 변수를 사용하여 위치 지정

Java 시스템 속성 및 O/S 환경 변수를 PathName 위치에 포함할 수 있습니다.

Java 시스템 속성은 ${PropertyName} 구문을 사용하여 위치 확인기에 포함될 수 있습니다. 예를 들어 Red Hat Fuse의 루트 디렉터리가 Java 시스템 속성인 karaf.home 에 저장된 경우 다음과 같이 파일 위치에 해당 디렉터리 값을 포함할 수 있습니다.

file:${karaf.home}/etc/foo.properties

O/S 환경 변수는 ${env:VarName} 구문을 사용하여 위치 확인기에 포함될 수 있습니다. 예를 들어, JBoss Fuse의 루트 디렉터리가 환경 변수 SMX_HOME 에 저장된 경우 다음과 같이 파일 위치에 해당 디렉터리 값을 포함할 수 있습니다.

file:${env:SMX_HOME}/etc/foo.properties

2.7.5. 속성 구성 요소 구성

속성 자리 표시자 사용을 시작하기 전에 하나 이상의 속성 파일의 위치를 지정하여 속성 구성 요소를 구성해야 합니다.Before you can start using property placeholders, you must configure the properties component, specifying the locations of one or more property files.

Java DSL에서는 다음과 같이 속성 파일 위치를 사용하여 속성 구성 요소를 구성할 수 있습니다.

// Java
import org.apache.camel.component.properties.PropertiesComponent;
...
PropertiesComponent pc = new PropertiesComponent();
pc.setLocation("com/fusesource/cheese.properties,com/fusesource/bar.properties");
context.addComponent("properties", pc);

addComponent() 호출에 표시된 것처럼 속성 구성 요소의 이름을 속성으로 설정해야 합니다.

XML DSL에서는 다음과 같이 전용 propertyPlacholder 요소를 사용하여 속성 구성 요소를 구성할 수 있습니다.

<camelContext ...>
   <propertyPlaceholder
      id="properties"
      location="com/fusesource/cheese.properties,com/fusesource/bar.properties"
   />
</camelContext>

속성 구성 요소가 초기화될 때 누락된 .properties 파일을 무시하도록 하려면 ignoreMissingLocation 옵션을 true 로 설정하면 일반적으로 누락된 .properties 파일이 오류가 발생합니다.

또한 속성 구성 요소가 Java 시스템 속성 또는 O/S 환경 변수를 사용하여 지정된 누락된 위치를 무시하도록 하려면 ignoreMissingLocation 옵션을 true 로 설정할 수 있습니다.

2.7.6. 자리 표시자 구문

속성 구성 요소를 구성한 후 적절한 컨텍스트에서 자리 표시자를 자동으로 대체합니다.After it is configured, the property component automatically substitutes placeholders (in the appropriate context). 자리 표시자의 구문은 다음과 같이 컨텍스트에 따라 달라집니다.

  • 엔드 포인트 URI 및 Spring XML 파일에서 kafka -하겠습니다. 자리 표시자는 {{Key}} 로 지정됩니다.
  • XML DSL 특성을 설정할 때 Cryostat- xs:string 속성은 다음 구문을 사용하여 설정됩니다.

    AttributeName="{{Key}}"

    다른 특성 유형(예: xs:int 또는 xs:boolean)은 다음 구문을 사용하여 설정해야 합니다.

    prop:AttributeName="Key"

    여기서 prophttp://camel.apache.org/schema/placeholder 네임스페이스와 연결되어 있습니다.

  • Java DSL EIP 옵션을 설정할 때 Java DSL에서 EIP(Enterprise Integration Pattern) 명령에 옵션을 설정하려면 fluent DSL에 다음과 같은 자리 표시자() 절을 추가합니다.

    .placeholder("OptionName", "Key")
  • 단순 언어 표현식에서 밀리초---- 자리 표시자는 ${properties:Key} 로 지정됩니다.

2.7.7. 끝점 URI에서 대체

경로에 끝점 URI 문자열이 표시되는 경우 끝점 URI 구문 분석의 첫 번째 단계는 속성 자리 표시자 구문 분석기를 적용하는 것입니다. 자리 표시자 구문 분석기에서는 이중 중괄호, {{Key}} 사이에 나타나는 속성 이름을 자동으로 대체합니다. 예를 들어 예 2.4. “속성 파일 샘플” 에 표시된 속성 설정이 있는 경우 다음과 같이 경로를 정의할 수 있습니다.

from("{{cool.start}}")
    .to("log:{{cool.start}}?showBodyType=false&showExchangeId={{cool.showid}}")
    .to("mock:{{cool.result}}");

기본적으로 자리 표시자 구문 분석기에서는 레지스트리에서 속성 빈 ID를 조회하여 속성 구성 요소를 찾습니다. 원하는 경우 끝점 URI에서 스키마를 명시적으로 지정할 수 있습니다. 예를 들어 속성 앞에 각 끝점 URI를 접두사로 사용하면 다음과 같은 동등한 경로를 정의할 수 있습니다.

from("properties:{{cool.start}}")
    .to("properties:log:{{cool.start}}?showBodyType=false&showExchangeId={{cool.showid}}")
    .to("properties:mock:{{cool.result}}");

스키마를 명시적으로 지정할 때 속성 구성 요소에 대한 옵션을 지정하는 옵션도 있습니다. 예를 들어 속성 파일 위치를 재정의하려면 다음과 같이 위치 옵션을 설정할 수 있습니다.

from("direct:start").to("properties:{{bar.end}}?location=com/mycompany/bar.properties");

2.7.8. Spring XML 파일에서 대체

DSL 요소의 다양한 특성을 설정하기 위해 XML DSL에서 속성 자리 표시자를 사용할 수도 있습니다. 이 컨텍스트에서 placholder 구문은 이중 중괄호인 {{Key}} 를 사용합니다. 예를 들어 다음과 같이 속성 자리 표시자를 사용하여 jmxAgent 요소를 정의할 수 있습니다.

<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
    <propertyPlaceholder id="properties" location="org/apache/camel/spring/jmx.properties"/>

    <!-- we can use property placeholders when we define the JMX agent -->
    <jmxAgent id="agent" registryPort="{{myjmx.port}}"
              usePlatformMBeanServer="{{myjmx.usePlatform}}"
              createConnector="true"
              statisticsLevel="RoutesOnly"
            />

    <route>
        <from uri="seda:start"/>
        <to uri="mock:result"/>
    </route>
</camelContext>

2.7.9. XML DSL 특성 값 대체

예를 들어 < jmxAgent registryPort="{{myjmx.port}}" …​> …​ >와 같이 xs:string 유형의 속성 값을 지정하는 데 일반 자리 표시자 구문을 사용할 수 있습니다. 그러나 다른 유형의 속성(예: xs:int 또는 xs:boolean)의 경우 특수 구문, prop:AttributeName="Key" 를 사용해야 합니다.

예를 들어 속성 파일에서 stop.flag 속성을 정의하는 경우 true 값을 가지면 이 속성을 사용하여 다음과 같이 stopOnException 부울 속성을 설정할 수 있습니다.

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:prop="http://camel.apache.org/schema/placeholder"
       ... >

    <bean id="illegal" class="java.lang.IllegalArgumentException">
        <constructor-arg index="0" value="Good grief!"/>
    </bean>

    <camelContext xmlns="http://camel.apache.org/schema/spring">

        <propertyPlaceholder id="properties"
                             location="classpath:org/apache/camel/component/properties/myprop.properties"
                             xmlns="http://camel.apache.org/schema/spring"/>

        <route>
            <from uri="direct:start"/>
            <multicast prop:stopOnException="stop.flag">
                <to uri="mock:a"/>
                <throwException ref="damn"/>
                <to uri="mock:b"/>
            </multicast>
        </route>

    </camelContext>

</beans>
중요

이전 예제의 요소에 표시된 대로 prop 접두사를 Spring 파일의 http://camel.apache.org/schema/placeholder 네임스페이스에 명시적으로 할당해야 합니다.

2.7.10. Java DSL EIP 옵션 대체

Java DSL에서 EIP 명령을 호출할 때 자리 표시자 ("OptionName", "") 형식의 하위 복제를 추가하여 속성 자리 표시자 의 값을 사용하여 EIP 옵션을 설정할 수 있습니다.

예를 들어 속성 파일에서 stop.flag 속성을 정의하는 경우 true 값을 가지면 이 속성을 사용하여 다음과 같이 멀티 캐스트 EIP의 stopOnException 옵션을 설정할 수 있습니다.

from("direct:start")
    .multicast().placeholder("stopOnException", "stop.flag")
        .to("mock:a").throwException(new IllegalAccessException("Damn")).to("mock:b");

2.7.11. 간단한 언어 표현식의 대체

간단한 언어 표현식에서 속성 자리 표시자를 대체할 수도 있지만, 이 경우 자리 표시자의 구문은 ${properties:Key} 입니다. 예를 들어 다음과 같이 Simple 표현식 내에서 cheese.quote 자리 표시자를 대체할 수 있습니다.

from("direct:start")
    .transform().simple("Hi ${body} do you think ${properties:cheese.quote}?");

구문 ${properties:Key:DefaultVal} 구문을 사용하여 속성의 기본값을 지정할 수 있습니다. 예를 들면 다음과 같습니다.

from("direct:start")
    .transform().simple("Hi ${body} do you think ${properties:cheese.quote:cheese is good}?");

${properties-location:Location:Key} 구문을 사용하여 속성 파일의 위치를 재정의할 수도 있습니다. 예를 들어 com/mycompany/bar.properties 속성 파일의 설정을 사용하여 bar.quote 자리 표시자를 대체하려면 다음과 같이 Simple 표현식을 정의할 수 있습니다.

from("direct:start")
    .transform().simple("Hi ${body}. ${properties-location:com/mycompany/bar.properties:bar.quote}.");

2.7.12. XML DSL에서 속성 위치 소유자 사용

이전 릴리스에서는 xs:string 유형 속성이 XML DSL의 자리 표시자를 지원하는 데 사용되었습니다. 예를 들어 timeout 속성은 xs:int 유형입니다. 따라서 문자열 값을 자리 표시자 키로 설정할 수 없습니다.

Apache Camel 2.7 이후부터는 이제 특수 자리 표시자 네임스페이스를 사용하면 됩니다. 다음 예제에서는 네임스페이스에 대한 prop 접두사를 보여줍니다. XML DSL의 특성에서 prop 접두사를 사용할 수 있습니다.

참고

Multicast에서 stopOnException 옵션을 키가 stop 인 자리 표시자의 값으로 설정합니다. 또한 속성 파일에서 값을 로 정의합니다.

stop=true
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:prop="http://camel.apache.org/schema/placeholder"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
    ">

    <!-- Notice in the declaration above, we have defined the prop prefix as the Camel placeholder namespace -->

    <bean id="damn" class="java.lang.IllegalArgumentException">
        <constructor-arg index="0" value="Damn"/>
    </bean>

    <camelContext xmlns="http://camel.apache.org/schema/spring">

        <propertyPlaceholder id="properties"
                             location="classpath:org/apache/camel/component/properties/myprop.properties"
                             xmlns="http://camel.apache.org/schema/spring"/>

        <route>
            <from uri="direct:start"/>
            <!-- use prop namespace, to define a property placeholder, which maps to
                 option stopOnException={{stop}} -->
            <multicast prop:stopOnException="stop">
                <to uri="mock:a"/>
                <throwException ref="damn"/>
                <to uri="mock:b"/>
            </multicast>
        </route>

    </camelContext>

</beans>

2.7.13. OSGi 블루프린트 속성 자리 표시자와 통합

Red Hat Fuse OSGi 컨테이너에 경로를 배포하는 경우 Apache Camel 속성 자리 표시자 메커니즘을 JBoss Fuse의 블루프린트 속성 자리 표시자 메커니즘과 통합할 수 있습니다(실제로 통합은 기본적으로 활성화됨). 다음과 같이 통합을 설정하는 두 가지 기본 방법이 있습니다.

2.7.14. 암시적 블루프린트 통합

OSGi 블루프린트 파일 내에 camelContext 요소를 정의하면 Apache Camel 속성 자리 표시자 메커니즘이 블루프린트 속성 자리 표시자 메커니즘과 자동으로 통합됩니다. 즉, camelContext 범위 내에 표시되는 Apache Camel 구문(예: {{cool.end}})을 따르는 자리 표시자는 블루프린트 속성 자리 표시자 메커니즘을 확인하여 암시적으로 해결됩니다.

예를 들어, 경로의 마지막 끝점이 속성 자리 표시자인 {{result}}:에 의해 정의된 OSGi 블루프린트 파일에 다음 경로를 고려하십시오.

<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.0.0"
           xsi:schemaLocation="
           http://www.osgi.org/xmlns/blueprint/v1.0.0 https://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd">

    <!-- OSGI blueprint property placeholder -->
    <cm:property-placeholder id="myblueprint.placeholder" persistent-id="camel.blueprint">
        <!-- list some properties for this test -->
        <cm:default-properties>
            <cm:property name="result" value="mock:result"/>
        </cm:default-properties>
    </cm:property-placeholder>

    <camelContext xmlns="http://camel.apache.org/schema/blueprint">
        <!-- in the route we can use {{ }} placeholders which will look up in blueprint,
             as Camel will auto detect the OSGi blueprint property placeholder and use it -->
        <route>
            <from uri="direct:start"/>
            <to uri="mock:foo"/>
            <to uri="{{result}}"/>
        </route>
    </camelContext>

</blueprint>

블루프린트 속성 자리 표시자 메커니즘은 cm:property-placeholder hieradata를 생성하여 초기화됩니다. 이전 예에서 cm:property-placeholder hieradata는 camel.blueprint 영구 ID와 연결되어 있습니다. 여기서 영구 ID는 OSGi 구성 관리자 서비스의 관련 속성 그룹을 참조하는 표준 방법입니다. 즉, cm:property-placeholder hieradata는 camel.blueprint 영구 ID 아래에 정의된 모든 속성에 대한 액세스를 제공합니다. 또한 일부 속성( nested cm:property 요소 사용)에 기본값을 지정할 수도 있습니다.

블루프린트 컨텍스트에서 Apache Camel 자리 표시자 메커니즘은 8080 레지스트리에서 cm:property-placeholder 인스턴스를 검색합니다. 이러한 인스턴스를 찾으면 Apache Camel 자리 표시자 메커니즘을 자동으로 통합하여, {{result}} 와 같은 자리 표시자 메커니즘은 블루프린트 속성 자리 표시자 메커니즘에서 키를 조회하여 해결됩니다(이 예에서는 myblueprint.placeholder chain을 통해).

참고

기본 블루프린트 자리 표시자 구문( 블루프린트 속성 액세스)은 ${Key} 입니다. 따라서 camelContext 요소의 범위를 벗어나는 자리 표시자 구문은 ${Key} 입니다. 반면 camel Context 요소의 범위 내에서 사용해야 하는 자리 표시자 구문은 {{Key}} 입니다.

2.7.15. 명시적 블루프린트 통합

Apache Camel 속성 자리 표시자 메커니즘에서 해당 속성을 찾는 위치를 더 많이 제어하려면 propertyPlaceholder 요소를 정의하고 확인자 위치를 명시적으로 지정할 수 있습니다.

예를 들어 명시적 propertyPlaceholder 인스턴스를 생성한다는 점에서 이전 예제와 다른 다음 블루프린트 구성을 고려하십시오.

<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.0.0"
           xsi:schemaLocation="
           http://www.osgi.org/xmlns/blueprint/v1.0.0 ">https://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd">

    <!-- OSGI blueprint property placeholder -->
    <cm:property-placeholder id="myblueprint.placeholder" persistent-id="camel.blueprint">
        <!-- list some properties for this test -->
        <cm:default-properties>
            <cm:property name="result" value="mock:result"/>
        </cm:default-properties>
    </cm:property-placeholder>

    <camelContext xmlns="http://camel.apache.org/schema/blueprint">

        <!-- using Camel properties component and refer to the blueprint property placeholder by its id -->
        <propertyPlaceholder id="properties" location="blueprint:myblueprint.placeholder"/>

        <!-- in the route we can use {{ }} placeholders which will lookup in blueprint -->
        <route>
            <from uri="direct:start"/>
            <to uri="mock:foo"/>
            <to uri="{{result}}"/>
        </route>

    </camelContext>

</blueprint>

이전 예에서 propertyPlaceholder 요소는 위치를 블루프린트:myblueprint.placeholder 로 설정하여 사용할 cm:property-placeholder hieradata를 명시적으로 지정합니다. 즉, 블루프린트: resolver는 cm:property-placeholder hieradata의 ID, myblueprint.placeholder 임을 명시적으로 참조합니다.

이 구성 스타일은 블루프린트 파일에 정의된 cm:property-placeholder hieradata가 두 개 이상 있고 사용할 구성을 지정해야 하는 경우 유용합니다. 또한 쉼표로 구분된 위치 목록을 지정하여 여러 위치에서 속성을 소스할 수 있습니다. 예를 들어 cm:property-placeholder hieradata와 속성 파일 myproperties.properties 에서 속성을 조회하려면 classpath에서 propertyPlaceholder 요소를 다음과 같이 정의할 수 있습니다.

<propertyPlaceholder id="properties"
  location="blueprint:myblueprint.placeholder,classpath:myproperties.properties"/>

2.7.16. Spring 속성 자리 표시자와 통합

Spring XML 파일에서 XML DSL을 사용하여 Apache Camel 애플리케이션을 정의하는 경우 org.apache.camel.spring.spi.BridgePropertyPlaceConfigurer 유형의 Spring 메가바이트를 선언하여 Apache Camel 속성 자리 표시자 메커니즘을 Spring 속성 자리 표시자 메커니즘과 통합할 수 있습니다.

Apache Camel의 property Placeholder element 및 Spring's ctx:property-placeholder 요소를 Spring XML 파일에서 모두 대체하는 BridgeProperty Placeholder를 정의합니다. 그런 다음 Spring ${PropName} 구문 또는 Apache Camel {{PropName }} 구문을 사용하여 구성된 속성을 참조할 수 있습니다.

예를 들어 cheese.properties 파일에서 속성 설정을 읽는 브리지 속성 자리 표시자를 정의합니다.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:ctx="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

  <!-- Bridge Spring property placeholder with Camel -->
  <!-- Do not use <ctx:property-placeholder ... > at the same time -->
  <bean id="bridgePropertyPlaceholder"
        class="org.apache.camel.spring.spi.BridgePropertyPlaceholderConfigurer">
    <property name="location"
              value="classpath:org/apache/camel/component/properties/cheese.properties"/>
  </bean>

  <!-- A bean that uses Spring property placeholder -->
  <!-- The ${hi} is a spring property placeholder -->
  <bean id="hello" class="org.apache.camel.component.properties.HelloBean">
    <property name="greeting" value="${hi}"/>
  </bean>

  <camelContext xmlns="http://camel.apache.org/schema/spring">
    <!-- Use Camel's property placeholder {{ }} style -->
    <route>
      <from uri="direct:{{cool.bar}}"/>
      <bean ref="hello"/>
      <to uri="{{cool.end}}"/>
    </route>
  </camelContext>

</beans>
참고

또는 BridgePropertyPlaceholderConfigurerlocation 속성을 Spring 속성 파일을 가리키도록 설정할 수 있습니다. Spring 속성 파일 구문이 완전히 지원됩니다.

2.8. 스레드 모델

2.8.1. Java 스레드 풀 API

Apache Camel 스레딩 모델은 Sun의 JDK 1.5에서 먼저 사용 가능하게 된 강력한 Java 동시성 API인 Package java.util.concurrent 를 기반으로 합니다. 이 API의 주요 인터페이스는 스레드 풀을 나타내는 ExecutorService 인터페이스입니다. 동시성 API를 사용하면 다양한 시나리오를 대상으로 다양한 종류의 스레드 풀을 생성할 수 있습니다.

2.8.2. Apache Camel 스레드 풀 API

Apache Camel 스레드 풀 API는 Apache Camel 애플리케이션의 모든 스레드 풀에 대해 중앙 팩토리( org.apache.camel.spi.ExecutorServiceManager 유형)를 제공하여 Java 동시성 API를 기반으로 빌드됩니다. 이러한 방식으로 스레드 풀 생성을 중앙 집중화하면 다음과 같은 몇 가지 이점이 있습니다.

  • 유틸리티 클래스를 사용하여 스레드 풀 생성 간소화.
  • 스레드 풀을 정상 종료와 통합.
  • 로깅 및 관리에 유용한 정보를 제공하는 스레드가 자동으로 제공됩니다.

2.8.3. 구성 요소 스레딩 모델

일부 Apache Camel 구성 요소는 SEDA, JMS 및 Cryostatty Cryostat-의 경우 본질적으로 다중 스레드로 분류됩니다. 이러한 구성 요소는 모두 Apache Camel 스레딩 모델 및 스레드 풀 API를 사용하여 구현되었습니다.

자체 Apache Camel 구성 요소를 구현하려는 경우 스레드 코드를 Apache Camel 스레딩 모델과 통합하는 것이 좋습니다. 예를 들어 구성 요소에 스레드 풀이 필요한 경우 CamelContext의 ExecutorServiceManager 오브젝트를 사용하여 생성하는 것이 좋습니다.

2.8.4. 프로세서 스레딩 모델

Apache Camel의 표준 프로세서 중 일부는 기본적으로 자체 스레드 풀을 생성합니다. 이러한 스레딩 인식 프로세서는 Apache Camel 스레딩 모델과 통합되며 사용하는 스레드 풀을 사용자 지정할 수 있는 다양한 옵션을 제공합니다.

표 2.8. “프로세서 스레드 옵션” Apache Camel에 내장된 스레드 인식 프로세서에서 스레드 풀을 제어하고 설정하는 다양한 옵션을 보여줍니다.

표 2.8. 프로세서 스레드 옵션

프로세서Java DSLXML DSL

aggregate

parallelProcessing()
executorService()
executorServiceRef()
@parallelProcessing
@executorServiceRef

멀티 캐스트

parallelProcessing()
executorService()
executorServiceRef()
@parallelProcessing
@executorServiceRef

recipientList

parallelProcessing()
executorService()
executorServiceRef()
@parallelProcessing
@executorServiceRef

분할

parallelProcessing()
executorService()
executorServiceRef()
@parallelProcessing
@executorServiceRef

스레드

executorService()
executorServiceRef()
poolSize()
maxPoolSize()
keepAliveTime()
timeUnit()
maxQueueSize()
rejectedPolicy()
@executorServiceRef
@poolSize
@maxPoolSize
@keepAliveTime
@timeUnit
@maxQueueSize
@rejectedPolicy

wireTap

wireTap(String uri, ExecutorService executorService)
wireTap(String uri, String executorServiceRef)
@executorServiceRef

2.8.5. 스레드 DSL 옵션

스레드 프로세서는 스레드 풀을 경로에 도입하는 데 사용할 수 있는 범용 DSL 명령입니다. 스레드 풀을 사용자 지정하는 다음 옵션을 지원합니다.

poolSize()
풀에 있는 최소 스레드 수(및 초기 풀 크기).
maxPoolSize()
풀의 최대 스레드 수입니다.
keepAliveTime()
이 기간(초 단위로 지정)보다 오래 유휴 상태인 스레드가 있는 경우 종료됩니다.
timeUnit()
java.util.concurrent.TimeUnit 유형을 사용하여 지정된 시간 단위는 활성 상태를 유지합니다.
maxQueueSize()
이 스레드 풀이 들어오는 작업 큐에 저장할 수 있는 최대 보류 중인 작업 수입니다.
rejectedPolicy()
들어오는 작업 큐가 가득 차면 수행할 작업을 지정합니다. 참조 표 2.10. “스레드 풀 빌더 옵션”
참고

이전 스레드 풀 옵션은 executorServiceRef 옵션과 호환되지 않습니다 (예: 이러한 옵션을 사용하여 executorServiceRef 옵션에서 참조하는 스레드 풀의 설정을 재정의할 수 없습니다). Apache Camel은 이를 적용하기 위해 DSL을 검증합니다.

2.8.6. 기본 스레드 풀 생성

스레드 인식 프로세서 중 하나에 대한 기본 스레드 풀을 생성하려면 XML DSL에서 parallelProcessing () 하위 복제 또는 병렬Processing 특성을 사용하여 parallelProcessing 옵션을 활성화합니다.

예를 들어 Java DSL에서는 다음과 같이 기본 스레드 풀(스레드 풀이 동시에 멀티 캐스트 대상을 처리하는 데 사용되는) 멀티캐스트 프로세서를 호출할 수 있습니다.

from("direct:start")
  .multicast().parallelProcessing()
    .to("mock:first")
    .to("mock:second")
    .to("mock:third");

다음과 같이 XML DSL에서 동일한 경로를 정의할 수 있습니다.

<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
    <route>
        <from uri="direct:start"/>
        <multicast parallelProcessing="true">
            <to uri="mock:first"/>
            <to uri="mock:second"/>
            <to uri="mock:third"/>
        </multicast>
    </route>
</camelContext>

2.8.7. 기본 스레드 풀 프로필 설정

기본 스레드 풀은 기본 스레드 풀 프로필에서 설정을 사용하는 스레드 팩토리에 의해 자동으로 생성됩니다. 기본 스레드 풀 프로필에는 표 2.9. “기본 스레드 풀 프로필 설정” 에 표시된 설정이 있습니다(애플리케이션 코드에서 이러한 설정을 수정하지 않은 것으로 가정).

표 2.9. 기본 스레드 풀 프로필 설정

스레드 옵션기본값

maxQueueSize

1000

poolSize

10

maxPoolSize

20

keepAliveTime

60 (초)

rejectedPolicy

CallerRuns

2.8.8. 기본 스레드 풀 프로필 변경

모든 후속 기본 스레드 풀이 사용자 지정 설정으로 생성되도록 기본 스레드 풀 프로필 설정을 변경할 수 있습니다. Java 또는 Spring XML에서 프로필을 변경할 수 있습니다.

예를 들어 Java DSL에서는 다음과 같이 기본 스레드 풀 프로필에서 poolSize 옵션과 maxQueueSize 옵션을 사용자 지정할 수 있습니다.

// Java
import org.apache.camel.spi.ExecutorServiceManager;
import org.apache.camel.spi.ThreadPoolProfile;
...
ExecutorServiceManager manager = context.getExecutorServiceManager();
ThreadPoolProfile defaultProfile = manager.getDefaultThreadPoolProfile();

// Now, customize the profile settings.
defaultProfile.setPoolSize(3);
defaultProfile.setMaxQueueSize(100);
...

XML DSL에서는 다음과 같이 기본 스레드 풀 프로필을 사용자 지정할 수 있습니다.

<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
    <threadPoolProfile
        id="changedProfile"
        defaultProfile="true"
        poolSize="3"
        maxQueueSize="100"/>
    ...
</camelContext>

이전 XML DSL 예에서 defaultProfile 속성을 true 로 설정하는 것이 중요합니다. 그러지 않으면 스레드 풀 프로파일은 기본 스레드 풀 프로필을 대체하는 대신 사용자 지정 스레드 풀 프로필로 처리됩니다( “사용자 정의 스레드 풀 프로필 생성”참조).

2.8.9. 프로세서의 스레드 풀 사용자 정의

executorService 또는 executorServiceRef 옵션을 사용하여 스레딩 인식 프로세서에 대한 스레드 풀을 더 직접 지정할 수도 있습니다(이러한 옵션은 parallelProcessing 옵션 대신 사용됨). 다음과 같이 프로세서의 스레드 풀을 사용자 지정하는 데 사용할 수 있는 두 가지 방법이 있습니다.

  • 사용자 지정 스레드 풀 Cryostat-단일적으로 ExecutorService (스레드 풀) 인스턴스를 생성하고 executorService 옵션에 전달합니다.
  • 사용자 지정 스레드 풀 프로필 Cryostat - Cryostatcreate을 지정하고 사용자 지정 스레드 풀 팩토리를 등록합니다. executorServiceRef 옵션을 사용하여 이 팩토리를 참조하는 경우 프로세서는 팩토리를 자동으로 사용하여 사용자 지정 스레드 풀 인스턴스를 생성합니다.

executorServiceRef 옵션에 빈 ID를 전달하면 스레드링 인식 프로세서는 먼저 레지스트리에서 해당 ID가 있는 사용자 지정 스레드 풀을 찾습니다. 해당 ID에 등록된 스레드 풀이 없는 경우 프로세서는 레지스트리에서 사용자 지정 스레드 풀 프로필을 조회하고 사용자 지정 스레드 풀 프로필을 사용하여 사용자 지정 스레드 풀을 인스턴스화합니다.

2.8.10. 사용자 정의 스레드 풀 생성

사용자 지정 스레드 풀은 java.util.concurrent.ExecutorService 유형의 스레드 풀일 수 있습니다. Apache Camel에서는 스레드 풀 인스턴스를 생성하는 방법을 사용하는 것이 좋습니다.

  • org.apache.camel.builder.ThreadPoolBuilder 유틸리티를 사용하여 스레드 풀 클래스를 빌드합니다.
  • 현재 CamelContextorg.apache.camel.spi.ExecutorServiceManager 인스턴스를 사용하여 스레드 풀 클래스를 생성합니다.

결국 ThreadPoolBuilderExecutorServiceManager 인스턴스를 사용하여 정의되기 때문에 두 가지 접근 방식에는 크게 차이가 없습니다. 일반적으로 ThreadPoolBuilder 는 더 간단한 접근 방식을 제공하기 때문에 선호됩니다. 그러나 ExecutorServiceManager 인스턴스에 직접 액세스하여 생성할 수 있는 스레드 종류( ScheduledExecutorService)가 하나 이상 있습니다.

표 2.10. “스레드 풀 빌더 옵션” 새 사용자 지정 스레드 풀을 정의할 때 설정할 수 있는 ThreadPoolBuilder 클래스에서 지원하는 옵션을 표시합니다.

표 2.10. 스레드 풀 빌더 옵션

빌더 옵션설명

maxQueueSize()

이 스레드 풀이 들어오는 작업 큐에 저장할 수 있는 최대 보류 중인 작업 수를 설정합니다. 값 -1 은 바인딩되지 않은 큐를 지정합니다. 기본값은 기본 스레드 풀 프로필에서 가져옵니다.

poolSize()

풀의 최소 스레드 수를 설정합니다(초기 풀 크기이기도 함). 기본값은 기본 스레드 풀 프로필에서 가져옵니다.

maxPoolSize()

풀에 있을 수 있는 최대 스레드 수를 설정합니다. 기본값은 기본 스레드 풀 프로필에서 가져옵니다.

keepAliveTime()

이 기간(초 단위로 지정)보다 오래 유휴 상태인 스레드가 있는 경우 종료됩니다. 이렇게 하면 로드가 켜지면 스레드 풀을 축소할 수 있습니다. 기본값은 기본 스레드 풀 프로필에서 가져옵니다.

rejectedPolicy()

들어오는 작업 큐가 가득 차면 수행할 작업을 지정합니다. 가능한 값은 다음 네 가지로 지정할 수 있습니다.

CallerRuns
(기본값) 가장 최근 들어오는 작업을 실행하도록 호출자 스레드를 가져옵니다. 이 옵션은 호출기 스레드가 최신 들어오는 작업 처리를 완료할 때까지 더 많은 작업을 수신하지 못하도록 합니다.
Abort
예외를 throw하여 가장 최근 들어오는 작업을 중단합니다.
삭제
가장 최근에 들어오는 작업을 자동으로 삭제합니다.
DiscardOldest
가장 오래 처리되지 않은 작업을 삭제한 다음 작업 큐에서 가장 최근에 들어오는 작업을 큐에 추가하려고 시도합니다.

build()

사용자 정의 스레드 풀 빌드를 완료하고 build() 에 대한 인수로 지정된 ID 아래에 새 스레드 풀을 등록합니다.

Java DSL에서는 다음과 같이 ThreadPoolBuilder 를 사용하여 사용자 지정 스레드 풀을 정의할 수 있습니다.

// Java
import org.apache.camel.builder.ThreadPoolBuilder;
import java.util.concurrent.ExecutorService;
...
ThreadPoolBuilder poolBuilder = new ThreadPoolBuilder(context);
ExecutorService customPool = poolBuilder.poolSize(5).maxPoolSize(5).maxQueueSize(100).build("customPool");
...

from("direct:start")
  .multicast().executorService(customPool)
    .to("mock:first")
    .to("mock:second")
    .to("mock:third");

다음과 같이 개체 참조 customPoolexecutorService() 옵션에 직접 전달하는 대신, Quarkus ID를 executorServiceRef() 옵션에 전달하여 레지스트리의 스레드 풀을 조회할 수 있습니다.

// Java
from("direct:start")
  .multicast().executorServiceRef("customPool")
    .to("mock:first")
    .to("mock:second")
    .to("mock:third");

XML DSL에서는 threadPool 요소를 사용하여 ThreadPoolBuilder 에 액세스합니다. 그런 다음 executorServiceRef 특성을 사용하여 사용자 지정 스레드 풀을 참조하여 다음과 같이 Spring 레지스트리에서 ID로 스레드 풀을 조회할 수 있습니다.

<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
    <threadPool id="customPool"
                poolSize="5"
                maxPoolSize="5"
                maxQueueSize="100" />

    <route>
        <from uri="direct:start"/>
        <multicast executorServiceRef="customPool">
            <to uri="mock:first"/>
            <to uri="mock:second"/>
            <to uri="mock:third"/>
        </multicast>
    </route>
</camelContext>

2.8.11. 사용자 정의 스레드 풀 프로필 생성

생성할 사용자 지정 스레드 풀 인스턴스가 많은 경우 스레드 풀에 대해 팩토리 역할을 하는 사용자 지정 스레드 풀 프로필을 정의하는 것이 더 편리합니다. 스레드 인식 프로세서의 스레드 풀 프로필을 참조할 때마다 프로세서는 프로필을 자동으로 사용하여 새 스레드 풀 인스턴스를 만듭니다. Java DSL 또는 XML DSL에서 사용자 지정 스레드 풀 프로필을 정의할 수 있습니다.

예를 들어 Java DSL에서는 빈 ID, customProfile 을 사용하여 사용자 지정 스레드 풀 프로필을 생성하고 다음과 같이 경로 내에서 참조할 수 있습니다.

// Java
import org.apache.camel.spi.ThreadPoolProfile;
import org.apache.camel.impl.ThreadPoolProfileSupport;
...
// Create the custom thread pool profile
ThreadPoolProfile customProfile = new ThreadPoolProfileSupport("customProfile");
customProfile.setPoolSize(5);
customProfile.setMaxPoolSize(5);
customProfile.setMaxQueueSize(100);
context.getExecutorServiceManager().registerThreadPoolProfile(customProfile);
...
// Reference the custom thread pool profile in a route
from("direct:start")
  .multicast().executorServiceRef("customProfile")
    .to("mock:first")
    .to("mock:second")
    .to("mock:third");

XML DSL에서 threadPoolProfile 요소를 사용하여 사용자 지정 풀 프로필을 만듭니다(기본 스레드 풀 프로필이 아니므로 defaultProfile 옵션이 false 로 설정되도록 합니다). metrics ID, customProfile 을 사용하여 사용자 정의 스레드 풀 프로필을 생성하고 다음과 같이 경로 내에서 참조할 수 있습니다.

<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
    <threadPoolProfile
                id="customProfile"
                poolSize="5"
                maxPoolSize="5"
                maxQueueSize="100" />

    <route>
        <from uri="direct:start"/>
        <multicast executorServiceRef="customProfile">
            <to uri="mock:first"/>
            <to uri="mock:second"/>
            <to uri="mock:third"/>
        </multicast>
    </route>
</camelContext>

2.8.12. 구성 요소 간 스레드 풀 공유

일부 표준 폴링 기반 구성 요소는 File 및 FTP해야 할 구성 요소와 같이 사용할 스레드 풀을 지정할 수 있습니다. 이를 통해 여러 구성 요소가 동일한 스레드 풀을 공유하여 JVM의 전체 스레드 수를 줄일 수 있습니다.

예를 들어 Apache Camel 구성 요소 참조 가이드의 File2 참조 가이드와 Apache Camel 구성 요소 참조 가이드Ftp2 는 구성 요소의 ExecutorService 오브젝트를 지정하는 데 사용할 수 있는 scheduledExecutorService 속성을 노출합니다.

2.8.13. 스레드 이름 사용자 정의

애플리케이션 로그를 더 읽기 쉽게 만들려면 종종 스레드 이름을 사용자 지정하는 것이 좋습니다(로그에서 스레드를 식별하는 데 사용됨). 스레드 이름을 사용자 지정하려면 ExecutorServiceStrategy 클래스 또는 ExecutorServiceManager 클래스에서 setThreadNamePattern 메서드를 호출하여 스레드 이름 패턴 을 구성할 수 있습니다. 또는 스레드 이름 패턴을 설정하는 더 쉬운 방법은 CamelContext 오브젝트에 threadNamePattern 속성을 설정하는 것입니다.

다음 자리 표시자는 스레드 이름 패턴에서 사용할 수 있습니다.

#camelId#
현재 CamelContext 의 이름입니다.
#counter#
증가 카운터로 구현된 고유 스레드 식별자입니다.
#name#
일반 Camel 스레드 이름입니다.
#longName#
끝점 매개 변수를 포함할 수 있는 긴 스레드 이름).

다음은 스레드 이름 패턴의 일반적인 예입니다.

Camel (#camelId#) thread #counter# - #name#

다음 예제에서는 XML DSL을 사용하여 Camel 컨텍스트에서 threadNamePattern 속성을 설정하는 방법을 보여줍니다.

<camelContext xmlns="http://camel.apache.org/schema/spring"
              threadNamePattern="Riding the thread #counter#" >
  <route>
    <from uri="seda:start"/>
    <to uri="log:result"/>
    <to uri="mock:result"/>
  </route>
</camelContext>

2.9. 경로 시작 및 연결 제어

2.9.1. 개요

기본적으로 Apache Camel 애플리케이션( CamelContext 인스턴스에 표시된 대로)이 시작되고 Apache Camel 애플리케이션이 종료되면 경로가 자동으로 종료됩니다. 중요하지 않은 배포의 경우 종료 순서의 세부 사항은 일반적으로 중요하지 않습니다. 그러나 프로덕션 환경에서는 데이터 손실을 방지하기 위해 기존 작업을 종료 중에 완료해야 하는 경우가 많습니다. 또한 일반적으로 경로가 종료되는 순서를 제어하여 종속 항목이 위반되지 않도록 합니다(기존 작업이 완료되지 않도록).

이러한 이유로 Apache Camel은 애플리케이션의 정상 종료 를 지원하는 일련의 기능을 제공합니다. 정상 종료를 사용하면 경로 중지 및 시작을 완전히 제어할 수 있으므로 경로 종료 순서를 제어하고 현재 작업을 완료할 수 있습니다.

2.9.2. 경로 ID 설정

각 경로에 경로 ID를 할당하는 것이 좋습니다. 로깅 메시지 및 관리 기능을 보다 효과적으로 활용할 뿐만 아니라 경로 ID를 사용하면 경로 중지 및 시작을 보다 효과적으로 제어할 수 있습니다.

예를 들어 Java DSL에서는 다음과 같이 routeId() 명령을 호출하여 경로 ID인 myCustomerRouteId 를 경로에 할당할 수 있습니다.

from("SourceURI").routeId("myCustomRouteId").process(...).to(TargetURI);

XML DSL에서 다음과 같이 경로 요소의 id 속성을 설정합니다.

<camelContext id="CamelContextID" xmlns="http://camel.apache.org/schema/spring">
  <route id="myCustomRouteId" >
    <from uri="SourceURI"/>
    <process ref="someProcessorId"/>
    <to uri="TargetURI"/>
  </route>
</camelContext>

2.9.3. 경로 자동 시작 비활성화

기본적으로 CamelContext가 시작 시 알고 있는 모든 경로가 자동으로 시작됩니다. 그러나 특정 경로의 시작을 수동으로 제어하려는 경우 해당 경로에 대한 자동 시작을 비활성화할 수 있습니다.

Java DSL 경로가 자동으로 시작되는지 여부를 제어하려면 부울 인수(true 또는 false) 또는 문자열 인수(true 또는 false)를 사용하여 autoStartup 명령을 호출합니다. 예를 들어 다음과 같이 Java DSL에서 경로 자동 시작을 비활성화할 수 있습니다.

from("SourceURI")
  .routeId("nonAuto")
  .autoStartup(false)
  .to(TargetURI);

다음과 같이 autoStartup 속성을 false 로 설정하여 XML DSL에서 경로 자동 시작을 비활성화할 수 있습니다.

<camelContext id="CamelContextID" xmlns="http://camel.apache.org/schema/spring">
  <route id="nonAuto" autoStartup="false">
    <from uri="SourceURI"/>
    <to uri="TargetURI"/>
  </route>
</camelContext>

2.9.4. 수동으로 경로 시작 및 중지

CamelContext 인스턴스에서 startRoute()stopRoute() 메서드를 호출하여 언제든지 Java에서 경로를 수동으로 시작하거나 중지할 수 있습니다. 예를 들어, 경로 ID가 non auto인 경로를 시작하려면 다음과 같이 CamelContext 인스턴스인 context 에서 startRoute() 메서드를 호출합니다.

// Java
context.startRoute("nonAuto");

경로 ID가 아닌 자동 경로가 있는 경로를 중지하려면 다음과 같이 CamelContext 인스턴스인 context 에서 stopRoute() 메서드를 호출합니다.

// Java
context.stopRoute("nonAuto");

2.9.5. 경로의 시작 순서

기본적으로 Apache Camel은 결정적이지 않은 순서로 경로를 시작합니다. 그러나 일부 애플리케이션에서는 시작 순서를 제어하는 것이 중요할 수 있습니다. Java DSL에서 시작 순서를 제어하려면 양의 정수 값을 인수로 사용하는 startupOrder() 명령을 사용합니다. 가장 낮은 정수 값이 있는 경로가 먼저 시작되고 그 뒤에 시작 순서가 더 높은 경로가 있습니다.

예를 들어 다음 예에서 처음 두 경로는 seda:buffer 엔드포인트를 통해 함께 연결됩니다. 다음과 같이 시작 순서 (2 및 1)를 할당하여 두 번째 경로 세그먼트 이후 첫 번째 경로 세그먼트가 시작되도록 할 수 있습니다.

예 2.5. Java DSL의 시작 순서

from("jetty:http://fooserver:8080")
    .routeId("first")
    .startupOrder(2)
    .to("seda:buffer");

from("seda:buffer")
    .routeId("second")
    .startupOrder(1)
    .to("mock:result");

// This route's startup order is unspecified
from("jms:queue:foo").to("jms:queue:bar");

또는 Spring XML에서는 다음과 같이 경로 요소의 startupOrder 특성을 설정하여 동일한 효과를 얻을 수 있습니다.

예 2.6. XML DSL의 시작 순서

<route id="first" startupOrder="2">
    <from uri="jetty:http://fooserver:8080"/>
    <to uri="seda:buffer"/>
</route>

<route id="second" startupOrder="1">
    <from uri="seda:buffer"/>
    <to uri="mock:result"/>
</route>

<!-- This route's startup order is unspecified -->
<route>
    <from uri="jms:queue:foo"/>
    <to uri="jms:queue:bar"/>
</route>

각 경로에 고유한 시작 순서 값을 할당해야 합니다. 1000보다 작은 양의 정수 값을 선택할 수 있습니다. 1000개 이상의 값은 Apache Camel용으로 예약되어 있으며, 명시적 시작 값 없이 이러한 값을 경로에 자동으로 할당합니다. 예를 들어 위 예제의 마지막 경로에 시작 값 1000이 자동으로 할당되므로 처음 두 경로 후에 시작됩니다.

2.9.6. 종료 순서

CamelContext 인스턴스가 종료되면 Apache Camel은 플러그형 종료 전략을 사용하여 종료 순서를 제어합니다. 기본 shutdown 전략은 다음과 같은 종료 순서를 구현합니다.

  1. 경로는 시작 순서의 반대로 종료됩니다.
  2. 일반적으로 종료 전략은 현재 활성화된 교환이 처리 될 때까지 기다립니다. 그러나 작업 실행의 처리는 구성할 수 있습니다.
  3. 전반적으로 종료 시퀀스는 시간 초과(기본값, 300초)에 의해 바인딩됩니다. 종료 시퀀스가 이 시간 초과를 초과하면 일부 작업이 여전히 실행 중인 경우에도 shutdown 전략이 강제 종료됩니다.

2.9.7. 경로 종료 순서

경로는 시작 순서의 반대로 종료됩니다. 즉, 시작 순서가 startupOrder() 명령(Java DSL에서) 또는 startupOrder 특성( XML DSL에서)을 사용하여 정의되는 경우 종료되는 첫 번째 경로는 시작 순서에 의해 할당되는 가장 높은 정수 값을 가진 경로이며 종료할 마지막 경로는 시작 순서에 의해 할당되는 가장 낮은 정수 값을 가진 경로입니다.

예를 들어 예 2.5. “Java DSL의 시작 순서” 에서 종료할 첫 번째 경로 세그먼트는 ID가 번째인 경로입니다. 두 번째 경로 세그먼트는 ID가 있는 경로이고 두 번째 경로 세그먼트는 ID가 있는 경로입니다. 이 예제에서는 경로를 종료할 때 관찰해야 합니다. 외부에서 액세스 가능한 소비자 끝점을 노출하는 경로는 먼저 종료되어야 합니다. 이는 나머지 경로 그래프를 통한 메시지 흐름을 방지하는 데 도움이 되기 때문입니다.

참고

Apache Camel은 또한 shutdownRoute(Defer) 옵션을 제공합니다. 이 옵션을 사용하면 경로를 종료하려면 마지막 경로(시작 순서 값 제외)에 경로를 지정할 수 있습니다. 그러나 이 옵션은 거의 필요하지 않습니다. 이 옵션은 주로 이전 버전의 Apache Camel(또는 2.3에 대한 해결 방법)에 대한 해결 방법으로 필요한 경우 시작 순서와 동일한 순서로 경로가 종료될 수 있습니다.

2.9.8. 경로에서 실행 중인 작업 종료

종료 시 경로가 계속 메시지를 처리하는 경우 shutdown 전략은 일반적으로 경로를 종료하기 전에 현재 활성 교환이 처리를 완료할 때까지 기다립니다. 이 동작은 다음 값 중 하나를 사용할 수 있는 shutdownRunningTask 옵션을 사용하여 각 경로에 구성할 수 있습니다.

ShutdownRunningTask.CompleteCurrentTaskOnly
일반적으로 경로는 한 번에 하나의 메시지에서만 작동하므로 현재 작업이 완료된 후 안전하게 경로를 종료할 수 있습니다.
ShutdownRunningTask.CompleteAllTasks
배치 소비자를 정상적으로 종료하려면 이 옵션을 지정합니다. 일부 소비자 끝점(예: 파일, FTP, 메일, iBATIS, JPA)은 한 번에 메시지 배치에서 작동합니다. 이러한 끝점의 경우 현재 배치의 모든 메시지가 완료될 때까지 기다리는 것이 더 적절합니다.

예를 들어 파일 소비자 끝점을 정상적으로 종료하려면 다음 Java DSL 조각에 표시된 것처럼 CompleteAllTasks 옵션을 지정해야 합니다.

// Java
public void configure() throws Exception {
    from("file:target/pending")
        .routeId("first").startupOrder(2)
        .shutdownRunningTask(ShutdownRunningTask.CompleteAllTasks)
        .delay(1000).to("seda:foo");

    from("seda:foo")
        .routeId("second").startupOrder(1)
        .to("mock:bar");
}

다음과 같이 XML DSL에 동일한 경로를 정의할 수 있습니다.

<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
    <!-- let this route complete all its pending messages when asked to shut down -->
    <route id="first"
           startupOrder="2"
           shutdownRunningTask="CompleteAllTasks">
        <from uri="file:target/pending"/>
        <delay><constant>1000</constant></delay>
        <to uri="seda:foo"/>
    </route>

    <route id="second" startupOrder="1">
        <from uri="seda:foo"/>
        <to uri="mock:bar"/>
    </route>
</camelContext>

2.9.9. 종료 시간

종료 시간 초과의 기본값은 300초입니다. shutdown 전략에서 setTimeout() 메서드를 호출하여 시간 초과 값을 변경할 수 있습니다. 예를 들어 다음과 같이 시간 초과 값을 600초로 변경할 수 있습니다.

// Java
// context = CamelContext instance
context.getShutdownStrategy().setTimeout(600);

2.9.10. 사용자 정의 구성 요소와 통합

사용자 지정 Apache Camel 구성 요소( org.apache.camel.Service 인터페이스에서 상속됨)를 구현하는 경우 사용자 정의 코드가 org.apache.camel.spi.ShutdownPrepared 인터페이스를 구현하여 종료 알림을 받을 수 있습니다. 그러면 구성 요소에 종료를 준비하여 사용자 정의 코드를 실행할 수 있습니다.

2.9.1. RouteIdFactory

소비자 끝점에 따라 논리 이름으로 경로 ID를 할당할 수 있는 RouteIdFactory 를 추가할 수 있습니다.

예를 들어 seda가 있는 경로를 경로 입력으로 사용하거나 직접 구성 요소를 사용하는 경우 해당 이름을 경로 ID(예:)로 사용할 수 있습니다.

  • direct:foo- foo
  • Seda:bar- bar
  • JMS:orders- 순서

자동 할당된 이름을 사용하는 대신 경로에 논리 이름을 할당할 수 있는 NodeIdFactory 를 사용할 수 있습니다. 또한 경로 URL의 컨텍스트 경로를 이름으로 사용할 수도 있습니다. 예를 들어 RouteIDFactory 를 사용하려면 다음을 실행합니다.

context.setNodeIdFactory(new RouteIdFactory());
참고

나머지 엔드포인트에서 사용자 정의 경로 ID를 가져올 수 있습니다.

2.10. 스케줄링된 경로 정책

2.10.1. 예약된 경로 정책 개요

2.10.1.1. 개요

스케줄링된 경로 정책은 런타임 시 경로에 영향을 주는 이벤트를 트리거하는 데 사용할 수 있습니다. 특히 현재 사용 가능한 구현을 사용하면 정책에 의해 지정된 언제든지 경로를 시작, 중지, 일시 중지 또는 재개할 수 있습니다.

2.10.1.2. 작업 예약

예약된 경로 정책은 다음과 같은 종류의 이벤트를 트리거할 수 있습니다.

  • 지정된 시간(또는 시간)에 경로를 시작합니다. 이 이벤트는 경로가 현재 중지된 상태에 있는 경우에만 적용됩니다. 활성화를 기다립니다.
  • 지정된 시간(또는 시간)에 경로를 중지합니다. 이 이벤트는 경로가 현재 활성 상태인 경우에만 적용됩니다.
  • 경로 시작 시( from())에 지정된 대로 경로의 시작 시 소비자 끝점을 비활성화하십시오. 나머지 경로는 여전히 활성화되어 있지만 클라이언트는 경로에 새 메시지를 보낼 수 없습니다.
  • 경로 시작 시 소비자 끝점을 다시 활성화하여 경로를 완전히 활성 상태로 반환합니다.

2.10.1.3. Quartz 구성 요소

Quartz 구성 요소는 작업 스케줄러의 오픈 소스 구현인 Terracotta의 Quartz 를 기반으로 하는 타이머 구성 요소입니다. Quartz 구성 요소는 간단한 스케줄링 경로 정책과 cron 스케줄링 경로 정책 모두에 대한 기본 구현을 제공합니다.

2.10.2. 간단한 예약 경로 정책

2.10.2.1. 개요

간단한 스케줄링 경로 정책은 경로를 시작, 중지, 일시 중지 및 재개할 수 있는 경로 정책입니다. 여기서 이러한 이벤트의 타이밍은 초기 이벤트의 시간 및 날짜를 제공하고 (선택 사항) 특정 횟수의 후속 거절을 지정하여 정의합니다. 간단한 스케줄링 경로 정책을 정의하려면 다음 클래스의 인스턴스를 생성합니다.

org.apache.camel.routepolicy.quartz.SimpleScheduledRoutePolicy

2.10.2.2. 종속성

간단한 예약 경로 정책은 Quartz 구성 요소인 camel-quartz 에 따라 다릅니다. 예를 들어 Maven을 빌드 시스템으로 사용하는 경우 camel-quartz 아티팩트에 종속성을 추가해야 합니다.

2.10.2.3. Java DSL 예

예 2.7. “Java DSL 예제 of Simple Scheduled Route” Java DSL을 사용하여 시작하기 위해 경로를 예약하는 방법을 보여줍니다. 초기 시작 시간인 startTime 은 현재 시간 이후 3초로 정의됩니다. 또한 이 정책은 route starts RepeatCount를 1로 설정하고 routeStartRepeat Interval 을 3000밀리초로 설정하여 초기 시작 시간 3초 후 경로를 시작하도록 구성됩니다.

Java DSL에서는 경로에서 routePolicy() DSL 명령을 호출하여 경로 정책을 경로에 연결합니다.

예 2.7. Java DSL 예제 of Simple Scheduled Route

// Java
SimpleScheduledRoutePolicy policy = new SimpleScheduledRoutePolicy();
long startTime = System.currentTimeMillis() + 3000L;
policy.setRouteStartDate(new Date(startTime));
policy.setRouteStartRepeatCount(1);
policy.setRouteStartRepeatInterval(3000);

from("direct:start")
   .routeId("test")
   .routePolicy(policy)
   .to("mock:success");
참고

routePolicy() 를 여러 인수로 호출하여 경로에 여러 정책을 지정할 수 있습니다.

2.10.2.4. XML DSL 예

예 2.8. “XML DSL 예제 of Simple Scheduled Route” XML DSL을 사용하여 시작하도록 경로를 예약하는 방법을 보여줍니다.

XML DSL에서는 경로 요소에서 route PolicyRef 속성을 설정하여 경로 정책을 경로에 연결합니다.

예 2.8. XML DSL 예제 of Simple Scheduled Route

<bean id="date" class="java.util.Data"/>

<bean id="startPolicy" class="org.apache.camel.routepolicy.quartz.SimpleScheduledRoutePolicy">
    <property name="routeStartDate" ref="date"/>
    <property name="routeStartRepeatCount" value="1"/>
    <property name="routeStartRepeatInterval" value="3000"/>
</bean>

<camelContext xmlns="http://camel.apache.org/schema/spring">
    <route id="myroute" routePolicyRef="startPolicy">
        <from uri="direct:start"/>
        <to uri="mock:success"/>
    </route>
</camelContext>
참고

routePolicyRef 값을 쉼표로 구분된 polkit ID 목록으로 설정하여 경로에 여러 정책을 지정할 수 있습니다.

2.10.2.5. 날짜 및 시간 정의

간단한 스케줄링 경로 정책에 사용되는 트리거의 초기 시간은 java.util.Date 유형을 사용하여 지정됩니다. Date 인스턴스를 정의하는 가장 유연한 방법은 java.util.Gregorian Cryostat 클래스를 통해 수행됩니다. 편리한 생성자와 메서드를 사용하여 날짜를 정의한 다음 Cryostat .getTime()을 호출하여 Date 인스턴스를 가져옵니다.

예를 들어, 2011년 1월 1일 정오에 대한 시간 및 날짜를 정의하려면 다음과 같이 Cryostat 생성자를 호출합니다.

// Java
import java.util.GregorianCalendar;
import java.util.Calendar;
...
GregorianCalendar gc = new GregorianCalendar(
    2011,
    Calendar.JANUARY,
    1,
    12,  // hourOfDay
    0,   // minutes
    0    // seconds
);

java.util.Date triggerDate = gc.getTime();

또한 Cryo stat 클래스는 다른 시간대의 시간 정의를 지원합니다. 기본적으로 컴퓨터의 로컬 시간대를 사용합니다.

2.10.2.6. 정상 종료

경로를 중지하도록 간단한 스케줄링 경로 정책을 구성하면 경로 중지 알고리즘이 정상 종료 절차와 자동으로 통합됩니다( 2.9절. “경로 시작 및 연결 제어”참조). 즉, 작업은 경로를 종료하기 전에 현재 교환이 처리를 완료할 때까지 기다립니다. 그러나 경로가 교환 처리를 완료했는지 여부에 관계없이 지정된 시간 후에 경로를 강제로 중지할 수 있습니다.

2.10.2.7. 시간 초과에 로깅 Inflight 교환

정상 종료가 지정된 시간 제한 기간 내에 완전히 종료되지 않으면 Apache Camel에서 보다 공격적인 종료를 수행합니다. 이는 경로, 스레드 풀 등을 강제 종료합니다.

시간 초과 후 Apache Camel은 현재 진행 중인 교환에 대한 정보를 기록합니다. 교환 및 교환의 현재 경로의 출처를 기록합니다.

예를 들어 아래 로그는 route1에서 시작되며 현재 delay1 노드에서 동일한 route1에 있는 inflight 교환이 있음을 보여줍니다.

정상 종료 중에 org.apache.camel.impl.DefaultShutdownStrategy 에서 DEBUG 로깅 수준을 활성화하면 동일한 inflight 교환 정보를 기록합니다.

2015-01-12 13:23:23,656 [- ShutdownTask] INFO DefaultShutdownStrategy - There are 1 inflight exchanges:
InflightExchange: [exchangeId=ID-davsclaus-air-62213-1421065401253-0-3, fromRouteId=route1, routeId=route1, nodeId=delay1, elapsed=2007, duration=2017]

이러한 로그를 표시하지 않으려면 logInflightExchangesOnTimeout 옵션을 false로 설정하여 이 기능을 끌 수 있습니다.

  context.getShutdownStrategegy().setLogInflightExchangesOnTimeout(false);

2.10.2.8. 작업 예약

간단한 스케줄링 경로 정책을 사용하여 다음 스케줄링 작업 중 하나 이상을 정의할 수 있습니다.

2.10.2.9. 경로 시작

다음 표에는 하나 이상의 경로를 예약하는 매개변수가 나열되어 있습니다.

매개변수유형Default설명

routeStartDate

java.util.Date

없음

경로를 처음 시작할 날짜와 시간을 지정합니다.

routeStartRepeatCount

int

0

0이 아닌 값으로 설정하는 경우 경로를 시작해야 하는 횟수를 지정합니다.

routeStartRepeatInterval

long

0

시작 사이의 시간 간격을 밀리초 단위로 지정합니다.

2.10.2.10. 경로 중지

다음 표에는 하나 이상의 경로 중지를 예약하는 매개변수가 나열되어 있습니다.

매개변수유형Default설명

routeStopDate

java.util.Date

없음

경로를 처음 중지할 날짜와 시간을 지정합니다.

routeStopRepeatCount

int

0

0이 아닌 값으로 설정하면 경로를 중지한 횟수를 지정합니다.

routeStopRepeatInterval

long

0

중지 사이의 시간 간격을 밀리초 단위로 지정합니다.

routeStopGracePeriod

int

10000

경로를 강제 중지하기 전에 현재 교환이 처리를 완료할 때까지 대기하는 시간을 지정합니다. 무한 유예 기간의 경우 0으로 설정합니다.

routeStopTimeUnit

long

TimeUnit.MILLISECONDS

유예 기간의 시간 단위를 지정합니다.

2.10.2.11. 경로 일시 중단

다음 표에는 한 번 이상의 경로 일시 중지를 예약하는 매개변수가 나열되어 있습니다.

매개변수유형Default설명

routeSuspendDate

java.util.Date

없음

경로를 처음 일시 중단한 날짜와 시간을 지정합니다.

routeSuspendRepeatCount

int

0

0이 아닌 값으로 설정하는 경우 경로를 일시 중단해야 하는 횟수를 지정합니다.

routeSuspendRepeatInterval

long

0

일시 중단 사이의 시간 간격을 밀리초 단위로 지정합니다.

2.10.2.12. 경로 재시작

다음 표에는 하나 이상의 경로 재개를 예약하는 매개변수가 나열되어 있습니다.

매개변수유형Default설명

routeResumeDate

java.util.Date

없음

경로가 처음 다시 시작되는 날짜와 시간을 지정합니다.

routeResumeRepeatCount

int

0

0이 아닌 값으로 설정하는 경우 경로를 다시 시작해야 하는 횟수를 지정합니다.

routeResumeRepeatInterval

long

0

다시 시작 사이의 시간 간격을 밀리초 단위로 지정합니다.

2.10.3. cron 스케줄링된 경로 정책

2.10.3.1. 개요

cron 스케줄링 경로 정책은 cron 표현식을 사용하여 이러한 이벤트의 타이밍을 지정하는 경로를 시작, 중지, 일시 중지 및 재개할 수 있는 경로 정책입니다. cron 스케줄링 경로 정책을 정의하려면 다음 클래스의 인스턴스를 생성합니다.

org.apache.camel.routepolicy.quartz.CronScheduledRoutePolicy

2.10.3.2. 종속성

간단한 예약 경로 정책은 Quartz 구성 요소인 camel-quartz 에 따라 다릅니다. 예를 들어 Maven을 빌드 시스템으로 사용하는 경우 camel-quartz 아티팩트에 종속성을 추가해야 합니다.

2.10.3.3. Java DSL 예

예 2.9. “Java DSL 예: Cron Scheduled Route” Java DSL을 사용하여 시작하기 위해 경로를 예약하는 방법을 보여줍니다. 정책은 cron 표현식 \*/3 * * * ? 로 구성되며 3 초마다 시작 이벤트를 트리거합니다.

Java DSL에서는 경로에서 routePolicy() DSL 명령을 호출하여 경로 정책을 경로에 연결합니다.

예 2.9. Java DSL 예: Cron Scheduled Route

// Java
CronScheduledRoutePolicy policy = new CronScheduledRoutePolicy();
policy.setRouteStartTime("*/3 * * * * ?");

from("direct:start")
    .routeId("test")
    .routePolicy(policy)
    .to("mock:success");;
참고

routePolicy() 를 여러 인수로 호출하여 경로에 여러 정책을 지정할 수 있습니다.

2.10.3.4. XML DSL 예

예 2.10. “XML DSL 예제 Cron Scheduled 경로”XML DSL을 사용하여 시작하도록 경로를 예약하는 방법을 보여줍니다.

XML DSL에서는 경로 요소에서 route PolicyRef 속성을 설정하여 경로 정책을 경로에 연결합니다.

예 2.10. XML DSL 예제 Cron Scheduled 경로

<bean id="date" class="org.apache.camel.routepolicy.quartz.SimpleDate"/>

<bean id="startPolicy" class="org.apache.camel.routepolicy.quartz.CronScheduledRoutePolicy">
    <property name="routeStartTime" value="*/3 * * * * ?"/>
</bean>

<camelContext xmlns="http://camel.apache.org/schema/spring">
    <route id="testRoute" routePolicyRef="startPolicy">
        <from uri="direct:start"/>
        <to uri="mock:success"/>
    </route>
</camelContext>
참고

routePolicyRef 값을 쉼표로 구분된 polkit ID 목록으로 설정하여 경로에 여러 정책을 지정할 수 있습니다.

2.10.3.5. cron 표현식 정의

cron 표현식 구문에는 UNIX cron 유틸리티의 출처가 있으며 UNIX 시스템에서 백그라운드에서 실행되도록 작업을 예약합니다. cron 표현식은 효과적으로 단일 이벤트 또는 주기적으로 반복되는 여러 이벤트를 지정할 수 있는 날짜 및 시간을 와일드카드하는 구문입니다.

cron 표현식은 다음 순서로 6 또는 7 필드로 구성됩니다.

Seconds Minutes Hours DayOfMonth Month DayOfWeek [Year]

한 번만 발생하는 이벤트를 정의하지 않으려면 year 필드는 선택 사항이며 일반적으로 생략됩니다. 각 필드는 리터럴과 특수 문자의 혼합으로 구성됩니다. 예를 들어 다음 cron 표현식은 매일 자정에 한 번 실행되는 이벤트를 지정합니다.

0 0 24 * * ?

* 문자는 필드의 모든 값과 일치하는 와일드카드입니다. 따라서 앞의 표현식은 매달 매일 일치합니다. ? 문자는 더미 자리 표시자이며 *ignore 이 필드*를 의미합니다. DayOfMonth 필드 또는 DayOfWeek 필드에 항상 표시됩니다. 이 필드는 두 필드를 동시에 지정하는 논리적으로 일관성이 유지되지 않기 때문입니다. 예를 들어 하루에 한 번 발생하지만 월요일부터 금요일까지 실행되는 이벤트를 예약하려면 다음 cron 표현식을 사용합니다.

0 0 24 ? * MON-FRI

여기서 하이픈 문자는 범위 MON-FRI 를 지정합니다. 슬래시 문자 / 를 사용하여 증분을 지정할 수도 있습니다. 예를 들어 5분마다 이벤트가 실행되도록 지정하려면 다음 cron 표현식을 사용합니다.

0 0/5 * * * ?

cron 표현식 구문에 대한 자세한 설명은 CRON 표현식 에 대한 404 문서를 참조하십시오.

2.10.3.6. 작업 예약

cron 스케줄링 경로 정책을 사용하여 다음 스케줄링 작업 중 하나 이상을 정의할 수 있습니다.

2.10.3.7. 경로 시작

다음 표에는 하나 이상의 경로를 예약하는 매개변수가 나열되어 있습니다.

매개변수유형Default설명

routeStartString

문자열

없음

하나 이상의 경로 시작 이벤트를 트리거하는 cron 표현식을 지정합니다.

2.10.3.8. 경로 중지

다음 표에는 하나 이상의 경로 중지를 예약하는 매개변수가 나열되어 있습니다.

매개변수유형Default설명

routeStopTime

문자열

없음

하나 이상의 경로 중지 이벤트를 트리거하는 cron 표현식을 지정합니다.

routeStopGracePeriod

int

10000

경로를 강제 중지하기 전에 현재 교환이 처리를 완료할 때까지 대기하는 시간을 지정합니다. 무한 유예 기간의 경우 0으로 설정합니다.

routeStopTimeUnit

long

TimeUnit.MILLISECONDS

유예 기간의 시간 단위를 지정합니다.

2.10.3.9. 경로 일시 중단

다음 표에는 한 번 이상의 경로 일시 중지를 예약하는 매개변수가 나열되어 있습니다.

매개변수유형Default설명

routeSuspendTime

문자열

없음

하나 이상의 경로 일시 중지 이벤트를 트리거하는 cron 표현식을 지정합니다.

2.10.3.10. 경로 재시작

다음 표에는 하나 이상의 경로 재개를 예약하는 매개변수가 나열되어 있습니다.

매개변수유형Default설명

routeResumeTime

문자열

없음

하나 이상의 경로 재개 이벤트를 트리거하는 cron 표현식을 지정합니다.

2.10.4. 경로 정책 Cryostat

2.10.4.1. 경로 정책 internal 사용

Camel 2.14 사용 가능

모든 경로에 경로 정책을 사용하려면 org.apache.camel.spi.RoutePolicyFactory 를 각 경로에 대해 RoutePolicy 인스턴스를 생성하기 위한 팩토리로 사용할 수 있습니다. 이는 모든 경로에 동일한 종류의 경로 정책을 사용하려는 경우 사용할 수 있습니다. 그런 다음 팩토리를 한 번만 구성해야 하며 생성된 모든 경로에 정책이 할당됩니다.

다음과 같이 CamelContext에는 팩토리를 추가하는 API가 있습니다.

context.addRoutePolicyFactory(new MyRoutePolicyFactory());

XML DSL에서 팩토리를 사용하여 < bean&gt;만 정의합니다.

<bean id="myRoutePolicyFactory" class="com.foo.MyRoutePolicyFactory"/>

팩토리에는 경로 정책을 생성하기 위한 createRoutePolicy 방법이 포함되어 있습니다.

/**
 * Creates a new {@link org.apache.camel.spi.RoutePolicy} which will be assigned to the given route.
 *
 * @param camelContext the camel context
 * @param routeId      the route id
 * @param route        the route definition
 * @return the created {@link org.apache.camel.spi.RoutePolicy}, or <tt>null</tt> to not use a policy for this route
 */
RoutePolicy createRoutePolicy(CamelContext camelContext, String routeId, RouteDefinition route);

원하는 만큼의 경로 정책 팩토리를 보유할 수 있습니다. addRoutePolicyFactory 를 다시 호출하거나 XML에서 다른 팩토리를 < bean> 로 선언합니다.

2.11. Camel 경로 다시 로드

Apache Camel 2.19 릴리스에서는 편집기에서 XML 파일을 저장할 때 camel XML 경로를 실시간 다시 로드할 수 있으므로 다시 로드가 트리거됩니다. 다음을 사용할 때 이 기능을 사용할 수 있습니다.

  • Camel Main 클래스가 포함된 Camel 독립 실행형
  • Camel Spring Boot
  • from the camel:run maven plugin

그러나 CamelContext 에서 ReloadStrategy 를 설정하고 자체 사용자 정의 전략을 제공하여 수동으로 이 작업을 활성화할 수도 있습니다.

2.12. Camel Maven 플러그인

Camel Maven 플러그인은 다음 목표를 지원합니다.

  • Camel:run - Camel 애플리케이션을 실행하려면
  • Camel:validate - 잘못된 Camel 엔드포인트 URI에 대한 소스 코드 유효성 검사
  • Camel:route-coverage - 단위 테스트 후 Camel 경로 적용 범위 보고

2.12.1. Camel:run

Camel Maven 플러그인의 camel:run 목표는 Maven의 분기된 JVM에서 Camel Spring 구성을 실행하는 데 사용됩니다. 시작하기 위한 좋은 예제 애플리케이션은 Spring Example입니다.

cd examples/camel-example-spring
mvn camel:run

이렇게 하면 main(…​) 방법을 작성하지 않고도 라우팅 규칙을 매우 쉽게 실행하고 테스트할 수 있습니다. 또한 다양한 라우팅 규칙 세트를 호스팅하고 독립적으로 테스트할 수 있도록 여러 개의 Cryostat를 생성할 수 있습니다. Camel Maven 플러그인은 maven 프로젝트의 소스 코드를 컴파일한 다음 META-INF/spring/*.xml 의 classpath에서 XML 구성 파일을 사용하여 Spring ApplicationContext를 부팅합니다. Camel 경로를 조금 더 빠르게 부팅하려면 대신 camel:embedded 를 시도할 수 있습니다.

2.12.1.1. 옵션

Camel Maven 플러그인 실행 목표는 명령줄에서 구성 하거나 <configuration> 태그의 pom.xml 파일에 정의된 다음 옵션을 지원합니다.

매개변수

기본값

설명

duration

-1

애플리케이션이 종료되기 전에 실행되는 시간(초)을 설정합니다. 값이 0이면 영구적으로 실행됩니다.

durationIdle

-1

애플리케이션을 종료하기 전에 유휴 상태로 설정할 수 있는 유휴 시간(초) 기간을 설정합니다. 값이 0이면 영구적으로 실행됩니다.

durationMaxMessages

-1

종료하기 전에 애플리케이션이 처리하는 최대 메시지 수를 설정합니다.

logClasspath

false

시작할 때 classpath를 기록할 지 여부

2.12.1.2. OSGi 블루프린트 실행

camel:run 플러그인은 블루프린트 애플리케이션 실행을 지원하며 기본적으로 OSGI-INF/blueprint/*.xml 에서 OSGi 블루프린트 파일을 스캔합니다. 아래 표시된 대로 blueprint를 true로 사용하여 블루프린트를 사용하도록 camel:run 플러그인을 구성해야 합니다.

<plugin>
  <groupId>org.jboss.redhat-fuse</groupId>
  <artifactId>camel-maven-plugin</artifactId>
  <configuration>
    <useBlueprint>true</useBlueprint>
  </configuration>
</plugin>

이를 통해 Camel과 관련이 있는지 여부에 관계없이 원하는 블루프린트 서비스를 부팅할 수 있습니다. camel:run 목표는 카l-blueprint가 classpath에 있는지 또는 프로젝트에 블루프린트 XML 파일이 있는지 자동 감지할 수 있으므로 더 이상 useBlueprint 옵션을 구성할 필요가 없습니다.

2.12.1.3. 제한된 블루프린트 컨테이너 사용

Felix Connector 프로젝트를 블루프린트 컨테이너로 사용합니다. 이 프로젝트는 완전한 가상 블루프린트 컨테이너가 아닙니다. 이를 위해 Apache Karaf 또는 Apache ServiceMix를 사용할 수 있습니다. applicationContextUri 구성을 사용하여 다음과 같은 명시적 블루프린트 XML 파일을 지정할 수 있습니다.

<plugin>
  <groupId>org.jboss.redhat-fuse</groupId>
  <artifactId>camel-maven-plugin</artifactId>
  <configuration>
    <useBlueprint>true</useBlueprint>
    <applicationContextUri>myBlueprint.xml</applicationContextUri>
    <!-- ConfigAdmin options which have been added since Camel 2.12.0 -->
    <configAdminPid>test</configAdminPid>
    <configAdminFileName>/user/test/etc/test.cfg</configAdminFileName>
  </configuration>
</plugin>

applicationContextUri 는 classpath에서 파일을 로드하므로 위의 예제에서는 myBlueprint.xml 파일이 classpath의 루트에 있어야 합니다. configAdminPid 는 지속성 속성 파일을 로드할 때 구성 관리 서비스의 pid 이름으로 사용되는 pid 이름입니다. configAdminFileName 은 구성 관리자 서비스 속성 파일을 로드하는 데 사용할 파일 이름입니다.

2.12.1.4. CDI 실행

camel:run 플러그인은 CDI 애플리케이션 실행도 지원합니다. 이를 통해 Camel 관련 또는 기타 CDI 활성화 서비스 여부에 관계없이 원하는 CDI 서비스를 부팅할 수 있습니다. 선택한 CDI 컨테이너(예: Weld 또는 OpenWebBeans)를 이 예제와 같이 camel-maven-plugin의 종속 항목에 추가해야 합니다. Camel 소스에서 다음과 같이 CDI 예제를 실행할 수 있습니다.

cd examples/camel-example-cdi
mvn compile camel:run

2.12.1.5. classpath 로깅

camel:run 을 실행할 때 classpath를 로깅해야 하는지 여부를 구성할 수 있습니다. 다음을 사용하여 구성에서 이 기능을 활성화할 수 있습니다.

<plugin>
  <groupId>org.jboss.redhat-fuse</groupId>
  <artifactId>camel-maven-plugin</artifactId>
  <configuration>
    <logClasspath>true</logClasspath>
  </configuration>
</plugin>

2.12.1.6. XML 파일의 실시간 다시 로드 사용

XML 파일 변경 사항을 스캔하고 해당 XML 파일에 포함된 Camel 경로를 다시 로드하도록 플러그인을 구성할 수 있습니다.

<plugin>
  <groupId>org.jboss.redhat-fuse</groupId>
  <artifactId>camel-maven-plugin</artifactId>
  <configuration>
    <fileWatcherDirectory>src/main/resources/META-INF/spring</fileWatcherDirectory>
  </configuration>
</plugin>

그런 다음 플러그인은 이 디렉터리를 조사합니다. 이를 통해 편집기에서 소스 코드를 편집하고 파일을 저장하고 실행 중인 Camel 애플리케이션에서 해당 변경 사항을 활용할 수 있습니다. 지원되는 Camel 경로 변경(예: <routes> 또는 < route >)만 변경합니다. Spring 또는 OSGi 블루프린트 < bean> 요소는 변경할 수 없습니다.

2.12.2. Camel:validate

다음 Camel 기능에 대한 소스 코드 검증의 경우:

  • 엔드포인트 URI
  • 간단한 표현식 또는 서술자
  • 중복 경로 ID

그런 다음 명령줄에서 camel:validate 목표를 실행하거나 IDEA 또는 Eclipse와 같은 Java 편집기에서 실행할 수 있습니다.

mvn camel:validate

이러한 오류를 파악하기 위해 플러그인을 빌드의 일부로 자동 실행하도록 활성화할 수도 있습니다.

<plugin>
  <groupId>org.jboss.redhat-fuse</groupId>
  <artifactId>camel-maven-plugin</artifactId>
  <executions>
    <execution>
      <phase>process-classes</phase>
      <goals>
        <goal>validate</goal>
      </goals>
    </execution>
  </executions>
</plugin>

단계는 플러그인이 실행되는 시기를 결정합니다. 위의 샘플에서 단계는 기본 소스 코드를 컴파일한 후 실행되는 프로세스 클래스입니다. maven 플러그인은 테스트 소스 코드의 유효성을 검사하도록 구성할 수도 있습니다. 즉, 다음과 같이 process-test-classes 에 따라 단계를 변경해야 합니다.

<plugin>
  <groupId>org.jboss.redhat-fuse</groupId>
  <artifactId>camel-maven-plugin</artifactId>
  <executions>
    <execution>
      <configuration>
        <includeTest>true</includeTest>
      </configuration>
      <phase>process-test-classes</phase>
      <goals>
        <goal>validate</goal>
      </goals>
    </execution>
  </executions>
</plugin>

2.12.2.1. 모든 Maven 프로젝트에서 목표 실행

pom.xml 파일에 플러그인을 추가하지 않고도 Maven 프로젝트에서 검증 목표를 실행할 수도 있습니다. 이렇게 하려면 정규화된 이름을 사용하여 플러그인을 지정해야 합니다. 예를 들어 Apache Camel의 camel-example-cdi 목표를 실행하려면 다음을 실행할 수 있습니다.

$cd camel-example-cdi
$mvn org.apache.camel:camel-maven-plugin:2.20.0:validate

그러면 다음을 실행하고 출력합니다.

[INFO] ------------------------------------------------------------------------
[INFO] Building Camel :: Example :: CDI 2.20.0
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- camel-maven-plugin:2.20.0:validate (default-cli) @ camel-example-cdi ---
[INFO] Endpoint validation success: (4 = passed, 0 = invalid, 0 = incapable, 0 = unknown components)
[INFO] Simple validation success: (0 = passed, 0 = invalid)
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

검증이 통과되고 4개의 끝점이 검증되었습니다. 이제 다음과 같은 소스 코드에서 Camel 엔드포인트 URI 중 하나에 오타를 발생했다고 가정합니다.

@Uri("timer:foo?period=5000")

기간 옵션에 오타 오류를 포함하도록 변경됨

@Uri("timer:foo?perid=5000")

검증 목표를 다시 실행하면 다음이 보고됩니다.

[INFO] ------------------------------------------------------------------------
[INFO] Building Camel :: Example :: CDI 2.20.0
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- camel-maven-plugin:2.20.0:validate (default-cli) @ camel-example-cdi ---
[WARNING] Endpoint validation error at: org.apache.camel.example.cdi.MyRoutes(MyRoutes.java:32)

	timer:foo?perid=5000

	                   perid    Unknown option. Did you mean: [period]


[WARNING] Endpoint validation error: (3 = passed, 1 = invalid, 0 = incapable, 0 = unknown components)
[INFO] Simple validation success: (0 = passed, 0 = invalid)
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

2.12.2.2. 옵션

Camel Maven 플러그인 검증 목표는 명령줄에서 구성 하거나 <configuration> 태그의 pom.xml 파일에 정의된 다음 옵션을 지원합니다.

매개변수

기본값

설명

downloadVersion

true

인터넷에서 Camel 카탈로그 버전을 다운로드할 수 있는지 여부입니다. 이 플러그인은 기본적으로 프로젝트에 다른 Camel 버전을 사용하는 경우 필요합니다.

failOnError

false

유효하지 않은 Camel 엔드 포인트가 발견되면 실패할지 여부입니다. 기본적으로 플러그인은 WARN 수준에서 오류를 기록합니다.

logUnparseable

false

비교할 수 없는 끝점 URI를 로깅할지 여부이므로 검증할 수 없습니다.

includeJava

true

잘못된 Camel 엔드포인트에 대해 검증할 Java 파일을 포함할지 여부입니다.

includeXml

true

잘못된 Camel 엔드포인트에 대해 검증할 XML 파일을 포함할지 여부입니다.

includeTest

false

테스트 소스 코드를 포함할지 여부입니다.

includes

 

지정된 패턴 목록(wildcard 및 정규식)과 일치하는 파일만 포함하도록 java 및 xml 파일의 이름을 필터링합니다. 여러 값을 쉼표로 구분할 수 있습니다.

excludes

 

지정된 패턴 목록(wildcard 및 정규식)과 일치하는 파일을 제외하도록 java 및 xml 파일의 이름을 필터링하려면 다음을 수행합니다. 여러 값을 쉼표로 구분할 수 있습니다.

ignoreUnknownComponent

true

알 수 없는 구성 요소를 무시할지 여부입니다.

ignoreIncapable

true

끝점 URI 또는 단순 표현식을 구문 분석할 수 없는 무시 여부입니다.

ignoreLenientProperties

true

lenient 속성을 사용하는 구성 요소를 무시할지 여부입니다. 이 값이 true인 경우 URI 유효성 검사가 더 빠름이지만 구성 요소의 일부가 아닌 속성에 대해 실패하지만 권한 있는 속성을 사용하므로 URI에서 실패합니다. 예를 들어 HTTP 구성 요소를 사용하여 엔드포인트 URI에 쿼리 매개변수를 제공합니다.

ignoreDeprecated

true

Camel 2.23 끝점 URI에서 더 이상 사용되지 않는 옵션을 무시할지 여부입니다.

duplicateRouteId

true

Camel 2.20 중복 경로 ID의 유효성을 검증할지 여부입니다. 경로 ID는 고유해야 하며 중복된 경우 Camel이 시작되지 않습니다.

directOrSedaPairCheck

true

Camel 2.23 기존 소비자로 전송되는 직접/스eda 끝점의 유효성을 검증할지 여부입니다.

showAll

false

모든 끝점 및 간단한 표현식을 표시할지 여부(잘못된 및 유효함).

예를 들어 명령줄에서 더 이상 사용되지 않는 옵션 사용을 무시하려면 다음을 실행할 수 있습니다.

$mvn camel:validate -Dcamel.ignoreDeprecated=false

camel. ignoreDeprecated 를 옵션 이름으로 사용하여 -D 명령 인수 앞에 붙여야 합니다.

2.12.2.3. include 테스트를 사용하여 끝점 검증

Maven 프로젝트가 있는 경우 플러그인을 실행하여 단위 테스트 소스 코드에서 끝점을 검증할 수 있습니다. 다음과 같이 -D 스타일을 사용하여 옵션을 전달할 수 있습니다.

$cd myproject
$mvn org.apache.camel:camel-maven-plugin:2.20.0:validate -DincludeTest=true

2.12.3. Camel:route-coverage

단위 테스트에서 Camel 경로 적용 범위 보고서를 생성하기 위해 다음을 수행합니다. 이를 사용하여 Camel 경로의 어떤 부분이 사용되었는지 확인할 수 있습니다.

2.12.3.1. 경로 적용 범위 활성화

다음 중 하나를 사용하여 단위 테스트를 실행하는 동안 경로 범위를 활성화할 수 있습니다.

  • 모든 테스트 클래스에 대해 글로벌 JVM 시스템 속성 설정
  • camel-test-spring 모듈을 사용하는 경우 테스트 클래스당 @EnableRouteCoverage 주석 사용
  • camel-test 모듈을 사용하는 경우 테스트 클래스당 isDumpRouteCoverage 메서드 덮어쓰기

2.12.3.2. JVM 시스템 속성을 사용하여 경로 적용 범위 활성화

JVM 시스템 속성 CamelTestRouteCoverage 를 켜면 모든 테스트 케이스에 대한 라우팅 범위를 활성화할 수 있습니다. 이 작업은 maven-surefire-plugin 의 구성에서 수행할 수 있습니다.

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-surefire-plugin</artifactId>
  <configuration>
    <systemPropertyVariables>
      <CamelTestRouteCoverage>true</CamelTestRouteCoverage>
    </systemPropertyVariables>
  </configuration>
</plugin>

또는 테스트를 실행할 때 명령줄에서 다음을 수행합니다.

mvn clean test -DCamelTestRouteCoverage=true

2.12.3.3. @EnableRouteCoverage 주석을 통해 활성화

camel-test-spring 을 사용하여 테스트하는 경우 테스트 클래스에 @EnableRouteCoverage 주석을 추가하여 단위 테스트 클래스에서 라우팅 범위를 활성화할 수 있습니다.

@RunWith(CamelSpringBootRunner.class)
@SpringBootTest(classes = SampleCamelApplication.class)
@EnableRouteCoverage
public class FooApplicationTest {

2.12.3.4. isDumpRouteCoverage 방법을 통해 활성화

그러나 camel-test 를 사용하고 단위 테스트가 CamelTestSupport 를 확장하는 경우 다음과 같이 경로 범위를 설정할 수 있습니다.

@Override
public boolean isDumpRouteCoverage() {
    return true;
}

RouteCoverage 메서드에서 범위를 지정할 수 있는 경로에는 고유한 ID가 할당되어야 합니다. 즉, 익명 경로를 사용할 수 없습니다. Java DSL에서 routeId 를 사용하여 이 작업을 수행합니다.

from("jms:queue:cheese").routeId("cheesy")
  .to("log:foo")
  ...

그리고 XML DSL에서는 id 속성을 통해 경로 ID를 할당하기만 하면 됩니다.

<route id="cheesy">
  <from uri="jms:queue:cheese"/>
  <to uri="log:foo"/>
  ...
</route>

2.12.3.5. 경로 범위 보고서 생성

TO generate the route coverage report, run the unit test with:

mvn test

그런 다음 다음을 실행하여 경로 범위를 보고할 수 있습니다.

mvn camel:route-coverage

이 보고서는 정확한 소스 코드 라인 보고를 사용하여 경로 범위가 누락된 경로를 보고합니다.

[INFO] --- camel-maven-plugin:2.21.0:route-coverage (default-cli) @ camel-example-spring-boot-xml ---
[INFO] Discovered 1 routes
[INFO] Route coverage summary:

File:	src/main/resources/my-camel.xml
RouteId:	hello

  Line #      Count   Route
  ------      -----   -----
      28          1   from
      29          1     transform
      32          1     filter
      34          0       to
      36          1     to

Coverage: 4 out of 5 (80.0%)

여기에서 의 두 번째 마지막 행에는 count 열에 0 이 있으므로 적용되지 않습니다. 또한 my-camel.xml XML 파일에 있는 소스 코드 파일에서 34행임을 알 수 있습니다.

2.12.3.6. 옵션

Camel Maven 플러그인 적용 범위는 명령줄에서 구성 하거나 <configuration> 태그의 pom.xml 파일에 정의된 다음 옵션을 지원합니다.

매개변수

기본값

설명

failOnError

false

경로 중 하나에 100% 범위가 없는 경우 실패할지 여부입니다.

includeTest

false

테스트 소스 코드를 포함할지 여부입니다.

includes

 

지정된 패턴 목록(wildcard 및 정규식)과 일치하는 파일만 포함하도록 java 및 xml 파일의 이름을 필터링합니다. 여러 값을 쉼표로 구분할 수 있습니다.

excludes

 

지정된 패턴 목록(wildcard 및 정규식)과 일치하는 파일을 제외하도록 java 및 xml 파일의 이름을 필터링하려면 다음을 수행합니다. 여러 값을 쉼표로 구분할 수 있습니다.

anonymousRoutes

false

익명 경로 허용 여부(경로 ID가 할당되지 않은 라우팅). 경로 ID를 사용하면 경로 소스 코드와 라우팅 커버 데이터를 일치시키는 것이 더 안전합니다. 익명 경로는 소스 코드의 경로 중 어떤 경로에 해당하는지 정확히 확인하기가 더 어렵기 때문에 경로 적용 범위에 덜 안전합니다.

2.13. Apache Camel Standalone 실행

독립 실행형 애플리케이션으로 camel을 실행하면 애플리케이션을 실행하고 JVM이 종료될 때까지 계속 실행할 수 있는 Main 클래스를 제공합니다. org.apache.camel.main Java 패키지 내에서 MainListener 클래스를 찾을 수 있습니다.

다음은 Main 클래스의 구성 요소입니다.

  • org.apache.camel.Main 클래스의 Camel-core JAR
  • org.apache.camel.spring.Main 클래스의 Camel- spring JAR

다음 예제에서는 Camel에서 Main 클래스를 생성하고 사용하는 방법을 보여줍니다.

public class MainExample {

    private Main main;

    public static void main(String[] args) throws Exception {
        MainExample example = new MainExample();
        example.boot();
    }

    public void boot() throws Exception {
        // create a Main instance
        main = new Main();
        // bind MyBean into the registry
        main.bind("foo", new MyBean());
        // add routes
        main.addRouteBuilder(new MyRouteBuilder());
        // add event listener
        main.addMainListener(new Events());
        // set the properties from a file
        main.setPropertyPlaceholderLocations("example.properties");
        // run until you terminate the JVM
        System.out.println("Starting Camel. Use ctrl + c to terminate the JVM.\n");
        main.run();
    }

    private static class MyRouteBuilder extends RouteBuilder {
        @Override
        public void configure() throws Exception {
            from("timer:foo?delay={{millisecs}}")
                .process(new Processor() {
                    public void process(Exchange exchange) throws Exception {
                        System.out.println("Invoked timer at " + new Date());
                    }
                })
                .bean("foo");
        }
    }

    public static class MyBean {
        public void callMe() {
            System.out.println("MyBean.callMe method has been called");
        }
    }

    public static class Events extends MainListenerSupport {

        @Override
        public void afterStart(MainSupport main) {
            System.out.println("MainExample with Camel is now started!");
        }

        @Override
        public void beforeStop(MainSupport main) {
            System.out.println("MainExample with Camel is now being stopped!");
        }
    }
}

2.14. OnCompletion

2.14.1. 개요

OnCompletion DSL 이름은 작업 단위 가 완료될 때 수행할 작업을 정의하는 데 사용됩니다. 작업 단위는 전체 교환을 포함하는 Camel 개념입니다. 34.1절. “교환”을 참조하십시오. onCompletion 명령에는 다음과 같은 기능이 있습니다.

  • OnCompletion 명령의 범위는 글로벌 또는 경로당일 수 있습니다. 경로 범위는 글로벌 범위를 덮어씁니다.
  • OnCompletion 은 실패 시 성공 시 트리거되도록 구성할 수 있습니다.
  • onWhen 서술자는 특정 상황에서만 onCompletion 을 트리거하는 데 사용할 수 있습니다.
  • 기본값은 스레드 풀이 아니지만 스레드 풀을 사용할지 여부를 정의할 수 있습니다.

2.14.2. OnCompletion을 위한 경로만 범위

교환에 onCompletion DSL이 지정되면 Camel이 새 스레드를 구동합니다. 이를 통해 onCompletion 작업의 간섭 없이 원래 스레드를 계속할 수 있습니다. 경로는 하나의 onCompletion 만 지원합니다. 다음 예에서 onCompletion 은 교환이 성공 또는 실패로 완료되었는지 여부를 트리거합니다. 기본 동작입니다.

from("direct:start")
     .onCompletion()
         // This route is invoked when the original route is complete.
         // This is similar to a completion callback.
         .to("log:sync")
         .to("mock:sync")
     // Must use end to denote the end of the onCompletion route.
     .end()
     // here the original route contiues
     .process(new MyProcessor())
     .to("mock:result");

XML의 경우 형식은 다음과 같습니다.

<route>
    <from uri="direct:start"/>
    <!-- This onCompletion block is executed when the exchange is done being routed. -->
    <!-- This callback is always triggered even if the exchange fails. -->
    <onCompletion>
        <!-- This is similar to an after completion callback. -->
        <to uri="log:sync"/>
        <to uri="mock:sync"/>
    </onCompletion>
    <process ref="myProcessor"/>
    <to uri="mock:result"/>
</route>

실패 시 onCompletion 을 트리거하려면 onFailureOnly 매개변수를 사용할 수 있습니다. 마찬가지로 성공 시 onCompletion 을 트리거하려면 onCompleteOnly 매개변수를 사용합니다.

from("direct:start")
     // Here onCompletion is qualified to invoke only when the exchange fails (exception or FAULT body).
     .onCompletion().onFailureOnly()
         .to("log:sync")
         .to("mock:sync")
     // Must use end to denote the end of the onCompletion route.
     .end()
     // here the original route continues
     .process(new MyProcessor())
     .to("mock:result");

XML의 경우 onFailureOnlyonCompleteOnlyonCompletion 태그에서 부울로 표시됩니다.

<route>
    <from uri="direct:start"/>
    <!-- this onCompletion block will only be executed when the exchange is done being routed -->
    <!-- this callback is only triggered when the exchange failed, as we have onFailure=true -->
    <onCompletion onFailureOnly="true">
        <to uri="log:sync"/>
        <to uri="mock:sync"/>
    </onCompletion>
    <process ref="myProcessor"/>
    <to uri="mock:result"/>
</route>

2.14.3. 온Completion을 위한 글로벌 범위

두 개 이상의 경로에 대한 onCompletion 을 정의하려면 다음을 수행합니다.

// define a global on completion that is invoked when the exchange is complete
 onCompletion().to("log:global").to("mock:sync");

 from("direct:start")
     .process(new MyProcessor())
     .to("mock:result");

2.14.4. OnIf 사용

특정 상황에서 onCompletion 을 트리거하려면 on When 서술자를 사용합니다. 다음 예제는 메시지 본문에 Hello:이라는 단어가 포함된 경우 onCompletion 을 트리거합니다.

/from("direct:start")
     .onCompletion().onWhen(body().contains("Hello"))
         // this route is only invoked when the original route is complete as a kind
         // of completion callback. And also only if the onWhen predicate is true
         .to("log:sync")
         .to("mock:sync")
     // must use end to denote the end of the onCompletion route
     .end()
     // here the original route contiues
     .to("log:original")
     .to("mock:result");

2.14.5. 스레드 풀과 함께 또는 없는 온Completion 사용

Camel 2.14부터는 기본적으로 스레드 풀을 사용하지 않습니다. 스레드 풀을 강제로 사용하려면 executorService 를 설정하거나 parallelProcessing 을 true로 설정합니다. 예를 들어 Java DSL에서는 다음 형식을 사용합니다.

onCompletion().parallelProcessing()
     .to("mock:before")
     .delay(1000)
     .setBody(simple("OnComplete:${body}"));

XML의 경우 형식은 다음과 같습니다.

<onCompletion parallelProcessing="true">
   <to uri="before"/>
   <delay><constant>1000</constant></delay>
   <setBody><simple>OnComplete:${body}<simple></setBody>
 </onCompletion>

executorServiceRef 옵션을 사용하여 특정 스레드 풀을 참조합니다.

<onCompletion executorServiceRef="myThreadPool"
   <to uri="before"/>
   <delay><constant>1000</constant></delay>
   <setBody><simple>OnComplete:${body}</simple></setBody>
 </onCompletion>>

2.14.6. 소비자 전송 응답 전에 온Completion 실행

OnCompletion 은 다음 두 가지 모드로 실행할 수 있습니다.

  • AfterConsumer - 소비자가 완료된 후 실행되는 기본 모드
  • beforeConsumer - 소비자가 호출자에게 다시 응답을 쓰기 전에 실행됩니다. 이를 통해 OnCompletion 을 통해 특수 헤더 추가와 같은 교환을 수정하거나 Exchange를 응답 로거로 기록할 수 있습니다.

예를 들어 헤더로 생성된 를 응답에 추가하려면 다음과 같이 modeBeforeConsumer() 를 사용합니다.

.onCompletion().modeBeforeConsumer()
     .setHeader("createdBy", constant("Someone"))
 .end()

XML의 경우 mode 속성을 BeforeConsumer 로 설정합니다.

<onCompletion mode="BeforeConsumer">
   <setHeader headerName="createdBy">
     <constant>Someone</constant>
   </setHeader>
 </onCompletion>

2.15. 메트릭

2.15.1. 개요

Camel 2.14 사용 가능

Camel은 Camel 경로에 많은 기존 메트릭 통합을 제공하는 반면 Codahale 지표가 추가되었습니다. 이를 통해 최종 사용자는 Codahale 메트릭을 사용하여 수집하는 기존 데이터와 함께 Camel 라우팅 정보를 원활히 제공할 수 있습니다.

Codahale 메트릭을 사용하려면 다음이 필요합니다.

  1. camel-metrics 구성 요소 추가
  2. XML 또는 Java 코드에서 경로 메트릭 활성화

성능 메트릭은 표시 방법이 있는 경우에만 사용할 수 있습니다. metrics를 통해 사용할 수 있으므로, Cryostat와 통합할 수 있는 모든 종류의 모니터링 툴을 사용할 수 있습니다. 또한 실제 데이터는 100% Codehale JSON입니다.

2.15.2. 메트릭 경로 정책

단일 경로에 대한 Codahale 메트릭을 얻는 것은 경로별로 MetricsRoutePolicy 를 정의하여 수행할 수 있습니다.

Java에서 경로 정책으로 할당할 MetricsRoutePolicy 인스턴스를 생성합니다. 이는 아래에 표시되어 있습니다.

from("file:src/data?noop=true").routePolicy(new MetricsRoutePolicy()).to("jms:incomingOrders");

XML DSL에서 경로 정책으로 지정된 <bean >을 정의합니다. 예를 들면 다음과 같습니다.

<bean id="policy" class="org.apache.camel.component.metrics.routepolicy.MetricsRoutePolicy"/>

<camelContext xmlns="http://camel.apache.org/schema/spring">
  <route routePolicyRef="policy">
    <from uri="file:src/data?noop=true"/>
[...]

2.15.3. 메트릭 경로 정책 Cryostat

이 팩토리를 사용하면 Codahale 메트릭을 사용하여 경로 사용률 통계를 노출하는 각 경로에 RoutePolicy 를 추가할 수 있습니다. 아래 예제로 Java 및 XML에서 이 팩토리를 사용할 수 있습니다.

Java에서 다음과 같이 CamelContext 에 팩토리를 추가합니다.

context.addRoutePolicyFactory(new MetricsRoutePolicyFactory());

XML DSL에서 다음과 같이 < bean> 을 정의합니다.

<!-- use camel-metrics route policy to gather metrics for all routes -->
<bean id="metricsRoutePolicyFactory" class="org.apache.camel.component.metrics.routepolicy.MetricsRoutePolicyFactory"/>

다음과 같이 Java 코드에서 org.apache.camel.component.metrics.routepolicy.MetricsRegistryService 에서 com.codahale.metrics.MetricRegistry Registry를 유지할 수 있습니다.

MetricRegistryService registryService = context.hasService(MetricsRegistryService.class);
if (registryService != null) {
  MetricsRegistry registry = registryService.getMetricsRegistry();
  ...
}

2.15.4. 옵션

MetricsRoutePolicyFactoryMetricsRoutePolicy 는 다음 옵션을 지원합니다.

이름

기본

설명

durationUnit

TimeUnit.MILLISECONDS

메트릭 보고자에서 또는 통계를 json으로 덤프할 때 사용할 단위입니다.

jmxDomain

org.apache.camel.metrics

JXM 도메인 이름입니다.

metricsRegistry

 

공유 com.codahale.metrics.MetricRegistry 를 사용할 수 있습니다. 제공되지 않는 경우 Camel은 이 CamelContext에서 사용하는 공유 인스턴스를 생성합니다.

prettyPrint

false

통계를 json 형식으로 출력할 때 매우 인쇄를 사용할지 여부입니다.

rateUnit

TimeUnit.SECONDS

메트릭 보고기에서 또는 통계를 json으로 덤프할 때 사용할 단위입니다.

useJmx

false

com.codahale.metrics.JmxReporter 를 사용하여 good grained statistics to Cryostat에 대한 통계를 보고할지 여부입니다.

CamelContext에서 Cryostat를 활성화하면 MetricsRegistryService mbean이 Cryostat 트리의 서비스 유형 아래에 등록됩니다. mbean에는 json을 사용하여 통계를 출력하는 단일 작업이 있습니다. useJmx를 true로 설정하는 것은 통계 유형당 세분화된 mbeans를 원하는 경우에만 필요합니다.

2.16. Cryostat 이름 지정

2.16.1. 개요

Apache Camel을 사용하면 관리 이름 패턴을 정의하여 CamelContext 8080의 이름을 Cryostat에 표시할 수 있습니다. 예를 들어 다음과 같이 XML CamelContext 인스턴스의 이름 패턴을 사용자 지정할 수 있습니다.

<camelContext id="myCamel" managementNamePattern="#name#">
    ...
</camelContext>

CamelContext 8080의 이름 패턴을 명시적으로 설정하지 않으면 Apache Camel이 기본 이름 지정 전략으로 되돌아갑니다.

2.16.2. 기본 이름 지정 전략

기본적으로 OSGi 번들에 배포된 CamelContext 8080의 Cryostat 이름은 번들의 OSGi 심볼릭 이름과 동일합니다. 예를 들어 OSGi 심볼릭 이름이 MyCamelBundle 인 경우 Cryostat 이름은 MyCamelBundle 입니다. 번들에 CamelContext 가 두 개 이상 있는 경우 counter 값을 접미사로 추가하여 Cryostat 이름을 모호하게 합니다. 예를 들어 MyCamelBundle 번들에 Camel 컨텍스트가 여러 개인 경우 해당 Cryostat의 이름이 다음과 같이 지정됩니다.

MyCamelBundle-1
MyCamelBundle-2
MyCamelBundle-3
...

2.16.3. Cryostat 이름 지정 전략 사용자 정의

기본 이름 지정 전략의 한 가지 단점은 지정된 CamelContext 8080이 실행 사이에 동일한 Cryostat 이름을 갖도록 보장할 수 없다는 것입니다. 실행 간에 일관성을 높이려면 CamelContext 인스턴스에 대한 Cryostat 이름 패턴을 정의하여 더 정확하게 이름을 제어할 수 있습니다.

2.16.4. Java에서 이름 패턴 지정

Java의 CamelContext 에 이름 패턴을 지정하려면 다음과 같이 setNamePattern 메서드를 호출합니다.

// Java
context.getManagementNameStrategy().setNamePattern("#name#");

2.16.5. XML에서 이름 패턴 지정

XML의 CamelContext 에 이름 패턴을 지정하려면 다음과 같이 camelContext 요소에 managementNamePattern 속성을 설정합니다.

<camelContext id="myCamel" managementNamePattern="#name#">

2.16.6. 이름 패턴 토큰

리터럴 텍스트와 다음 토큰 중 하나를 혼합하여 Cryostat 이름 패턴을 구성할 수 있습니다.

표 2.11. Cryostat 이름 패턴 토큰

토큰설명

#camelId#

CamelContext 8080의 id 속성 값입니다.

#name#

#camelId# 과 동일합니다.

#counter#

증가 카운터( 1에서 시작)입니다.

#bundleId#

배포된 번들 (OSGi만 해당)의 OSGi 번들 ID입니다.

#symbolicName#

OSGi 심볼릭 이름 (OSGi만 해당).

#version#

OSGi 번들 버전 (OSGi만 해당).

2.16.7. 예

다음은 지원되는 토큰을 사용하여 정의할 수 있는 몇 가지 예제입니다.

<camelContext id="fooContext" managementNamePattern="FooApplication-#name#">
    ...
</camelContext>
<camelContext id="myCamel" managementNamePattern="#bundleID#-#symbolicName#-#name#">
    ...
</camelContext>

2.16.8. 모호한 이름

사용자 정의 이름 지정 패턴은 기본 이름 지정 전략을 재정의하므로 이 접근 방식을 사용하여 모호한 Cryostat 이름을 정의할 수 있습니다. 예를 들면 다음과 같습니다.

<camelContext id="foo" managementNamePattern="SameOldSameOld"> ... </camelContext>
...
<camelContext id="bar" managementNamePattern="SameOldSameOld"> ... </camelContext>

이 경우 시작 시 Apache Camel이 실패하고 Cryostat가 이미 예외가 존재하는 것으로 보고했습니다. 따라서 모호한 이름 패턴을 정의하지 않도록 주의해야 합니다.

2.17. 성능 및 최적화

2.17.1. 메시지 복사

allowUseOriginalMessage 옵션 기본 설정은 false 이며, 필요하지 않은 경우 원본 메시지에서 생성되는 복사본을 잘라냅니다. allowUseOriginalMessage 옵션을 활성화하려면 다음 명령을 사용합니다.

  • 오류 처리기 또는 onException 요소에서 useOriginalMessage=true 를 설정합니다.
  • Java 애플리케이션 코드에서 AllowUseOriginalMessage=true 를 설정한 다음 getOriginalMessage 메서드를 사용합니다.
참고

2.18 이전 Camel 버전에서는 allowUseOriginalMessage 의 기본 설정은 true입니다.

3장. 엔터프라이즈 통합 패턴 소개

초록

Apache Camel의 엔터프라이즈 통합 패턴은 Gregor Cryostathpe 및 Cryostatby Woolf가 작성한 것과 동일한 이름의 책에 의해 영향을 받습니다. 이러한 작성자가 설명하는 패턴은 엔터프라이즈 통합 프로젝트를 개발하기 위한 우수한 toolbox를 제공합니다. 통합 아키텍처 논의를 위한 공통 언어 제공 외에도 Apache Camel의 프로그래밍 인터페이스 및 XML 구성을 사용하여 많은 패턴을 직접 구현할 수 있습니다.

3.1. 패턴 개요

3.1.1. 엔터프라이즈 통합 패턴북

Apache Camel은 이 책의 대부분의 패턴, Gregor needhpe 및 Cryostatby Woolf의 Enterprise Integration Patterns 를 지원합니다.

3.1.2. 메시징 시스템

표 3.1. “메시징 시스템” 에 표시된 메시징 시스템 패턴에는 메시징 시스템을 구성하는 기본 개념과 구성 요소가 도입되었습니다.

표 3.1. 메시징 시스템

icon이름사용 사례

Message icon

그림 5.1. “메시지 패턴”

메시지 채널에 의해 연결된 두 애플리케이션이 정보를 교환하는 방법은 무엇입니까?

Message channel icon

그림 5.2. “메시지 채널 패턴”

하나의 애플리케이션이 메시징을 사용하여 다른 애플리케이션과 어떻게 통신합니까?

Message endpoint icon

그림 5.3. “메시지 끝점 패턴”

애플리케이션이 메시지를 보내고 수신하기 위해 메시징 채널에 연결하려면 어떻게 해야 합니까?

Pipes and filters icon

그림 5.4. “파이프 및 필터 패턴”

독립성과 유연성을 유지하면서 메시지에서 복잡한 처리를 어떻게 수행할 수 있습니까?

Message router icons

그림 5.7. “메시지 라우터 패턴”

정의된 조건 세트에 따라 메시지를 다른 필터로 전달할 수 있도록 개별 처리 단계를 분리하려면 어떻게 해야 합니까?

Message translator icon

그림 5.8. “메시지#159 패턴”

서로 다른 데이터 형식을 사용하는 시스템은 메시징을 사용하여 서로 어떻게 통신합니까?

3.1.3. 메시징 채널

메시징 채널은 메시징 시스템의 참가자를 연결하는 데 사용되는 기본 구성 요소입니다. 표 3.2. “메시징 채널” 의 패턴은 사용 가능한 다양한 종류의 메시징 채널을 설명합니다.

표 3.2. 메시징 채널

icon이름사용 사례

Point to point icon

그림 6.1. “채널 패턴 지정”

호출자가 문서를 수신하거나 호출을 수행할 것이라고 정확히 한 수신자가 어떻게 확신할 수 있습니까?

Publish subscribe icon

그림 6.2. “서브스크립션 채널 패턴 게시”

발신자는 모든 관심 있는 수신자에게 이벤트를 어떻게 브로드캐스트할 수 있습니까?

Dead letter icon

그림 6.3. “dead letter 채널 패턴”

메시지 시스템은 전달할 수 없는 메시지와 어떤 역할을 합니까?

Guaranteed delivery icon

그림 6.4. “보장된 제공 패턴”

메시징 시스템이 실패하더라도 보낸 사람이 메시지를 전달하려면 어떻게 해야 합니까?

Message bus icon

그림 6.5. “메시지 버스 패턴”

다른 애플리케이션에 영향을 주지 않고 하나 이상의 애플리케이션을 추가하거나 제거할 수 있도록 별도의 분리된 애플리케이션이 함께 작동하도록 하는 아키텍처는 무엇입니까?

3.1.4. 메시지 구성

표 3.3. “메시지 구조” 에 표시된 메시지 구성 패턴은 시스템을 통과하는 메시지의 다양한 양식과 기능을 설명합니다.

표 3.3. 메시지 구조

icon이름사용 사례

Correlation identifier icon

“개요”

요청자는 수신된 응답을 생성한 요청을 어떻게 식별합니까?

Return address icon

7.3절. “반환 주소”

담당자는 어디에서 응답을 보낼 수 있는지 어떻게 알 수 있습니까?

3.1.5. 메시지 라우팅

표 3.4. “메시지 라우팅” 에 표시된 메시지 라우팅 패턴은 메시지 스트림에 적용할 수 있는 다양한 알고리즘을 포함하여 메시지 채널을 함께 연결하는 다양한 방법을 설명합니다(메시지 본문을 수정하지 않음).

표 3.4. 메시지 라우팅

icon이름사용 사례

Content based router icon

8.1절. “콘텐츠 기반 라우터”

단일 논리 기능(예: 인벤토리 확인)의 구현이 여러 물리적 시스템에 분배되는 상황을 어떻게 처리합니까?

Message filter icon

8.2절. “메시지 필터”

구성 요소가 관심 없는 메시지를 수신하지 않도록 하려면 어떻게 해야 합니까?

Recipient List icon

8.3절. “수신자 목록”

메시지를 동적으로 지정된 수신자 목록으로 라우팅하려면 어떻게 해야 합니까?

Splitter icon

8.4절. “Splitter”

여러 요소가 포함된 경우 메시지를 어떻게 처리할 수 있으며 각 요소를 다른 방식으로 처리해야 합니까?

Aggregator icon

8.5절. “수집기”

개별 결과를 어떻게 결합할 수 있지만 관련 메시지는 전체로 처리할 수 있도록 어떻게 결합합니까?

Resequencer icon

8.6절. “Resequencer”

어떻게 관련 된 스트림의 스트림을 얻을 수 있지만 out-of-sequence, 메시지를 다시 올바른 순서로 다시 얻을 수 있습니까?

distribution aggregate icon

8.14절. “구성된 메시지 프로세서”

여러 요소로 구성된 메시지를 처리할 때 전체 메시지 흐름을 어떻게 유지 관리할 수 있으며 각 요소에 따라 다른 처리가 필요할 수 있습니까?

 

8.15절. “together-Gather”

메시지를 여러 수신자에게 보내야 할 때 전체 메시지 흐름을 유지하려면 어떻게 해야 합니까? 각 수신자는 응답을 보낼 수 있습니까?

Routing slip icon

8.7절. “라우팅 슬립”

설계 시 단계 시퀀스를 알 수 없고 메시지에 따라 다를 수 있는 일련의 처리 단계를 통해 메시지를 연속으로 라우팅하려면 어떻게 해야 합니까?

 

8.8절. “Throttler”

특정 엔드포인트가 과부하되지 않도록 메시지를 제한하거나 일부 외부 서비스와 합의된 SLA를 초과하지 않도록하려면 어떻게 해야 합니까?

 

8.9절. “Delayer”

메시지 전송을 지연하려면 어떻게 해야 합니까?

 

8.10절. “로드 밸런서”

여러 끝점에서 부하를 분산하려면 어떻게 해야 합니까?

 

8.11절. “Hystrix”

외부 서비스를 호출할 때 Hystrix 회로 차단기를 사용하려면 어떻게 해야 합니까? Camel 2.18의 새로운 기능.

 

8.12절. “서비스 호출”

레지스트리에서 서비스를 조회하여 분산 시스템에서 원격 서비스를 호출하는 방법은 무엇입니까? Camel 2.18의 새로운 기능.

 

8.13절. “멀티 캐스트”

동시에 여러 끝점에 메시지를 라우팅하려면 어떻게 해야 합니까?

 

8.16절. “loop”

루프에서 메시지 처리를 반복하려면 어떻게 해야 합니까?

 

8.17절. “sampling”

다운스트림 경로 과부하를 방지하기 위해 지정된 기간에 여러 메시지 중 하나의 메시지를 샘플링하려면 어떻게 해야 합니까?

3.1.6. 메시지 변환

표 3.5. “메시지 Cryostat” 에 표시된 메시지 변환 패턴은 다양한 용도로 메시지 내용을 수정하는 방법을 설명합니다.

표 3.5. 메시지 Cryostat

icon이름사용 사례

Content enricher icon

10.1절. “콘텐츠 Enricher”

메시지 원본기에 필요한 모든 데이터 항목이 없는 경우 다른 시스템과 어떻게 통신합니까?

Content filter icon

10.2절. “콘텐츠 필터”

몇 가지 데이터 항목에 관심이 있을 때 큰 메시지 처리를 간소화하려면 어떻게 해야 합니까?

store in library icon

10.4절. “클레임 확인 EIP”

정보 콘텐츠를 희생하지 않고 시스템 전체에서 전송되는 메시지의 데이터 볼륨을 어떻게 줄일 수 있습니까?

Normalizer icon

10.3절. “노멀라이저”

의미 체계적으로 동일하지만 다른 형식으로 도달하는 메시지는 어떻게 처리합니까?

 

10.5절. “정렬”

메시지 본문을 정렬하려면 어떻게 해야 합니까?

3.1.7. 메시징 끝점

메시징 끝점은 메시징 채널과 애플리케이션 간의 연결 지점을 나타냅니다. 표 3.6. “메시징 끝점” 에 표시된 메시징 끝점 패턴은 끝점에서 구성할 수 있는 다양한 기능과 서비스 특성을 설명합니다.

표 3.6. 메시징 끝점

icon이름사용 사례
 

11.1절. “메시징 매퍼”

두 항목을 서로 독립적으로 유지하면서 도메인 개체와 메시징 인프라 간에 데이터를 이동하는 방법은 무엇입니까?

Event driven icon

11.2절. “이벤트 기반 소비자”

애플리케이션에서 사용할 수 있을 때 메시지를 자동으로 사용하려면 어떻게 해야 합니까?

Polling consumer icon

11.3절. “폴링 소비자”

애플리케이션이 준비되었을 때 애플리케이션에서 메시지를 사용하는 방법은 무엇입니까?

Competing consumers icon

11.4절. “경쟁 소비자”

메시징 클라이언트는 어떻게 여러 메시지를 동시에 처리할 수 있습니까?

Message dispatcher icon

11.5절. “메시지 Dispatcher”

단일 채널의 여러 소비자는 메시지 처리를 어떻게 조정할 수 있습니까?

Selective consumer icon

11.6절. “선택적 소비자”

메시지 소비자는 어떻게 수신하려는 메시지를 선택할 수 있습니까?

Durable subscriber icon

11.7절. “Cryostat 구독자”

구독자가 수신 대기하지 않을 때 메시지가 누락되지 않도록 하려면 어떻게 해야 합니까?

 

11.8절. “idempotent 소비자”

메시지 수신자는 중복 메시지를 어떻게 처리할 수 있습니까?

Transactional client icon

11.9절. “트랜잭션 클라이언트”

클라이언트는 메시징 시스템을 사용하여 트랜잭션을 어떻게 제어할 수 있습니까?

Messaging gateway icon

11.10절. “메시징 게이트웨이”

나머지 애플리케이션에서 메시징 시스템에 대한 액세스를 캡슐화하려면 어떻게 해야 합니까?

Service activator icon

11.11절. “서비스 활성화기”

애플리케이션이 다양한 메시징 기술과 비메시징 기술을 통해 호출할 서비스를 설계하는 방법은 무엇입니까?

3.1.8. 시스템 관리

표 3.7. “System Management” 에 표시된 시스템 관리 패턴은 메시징 시스템을 모니터링, 테스트 및 관리하는 방법을 설명합니다.

표 3.7. System Management

icon이름사용 사례

Wire tap icon

12장. System Management

점대점 채널에서 이동하는 메시지를 어떻게 검사합니까?

4장. REST 서비스 정의

초록

Apache Camel은 REST 서비스를 정의하는 여러 방법을 지원합니다. 특히 Apache Camel은 REST DSL(Domain Specific Language)을 제공합니다. 이는 REST 구성 요소를 통해 계층화할 수 있고 OpenAPI 와의 통합을 제공하는 간단하면서도 강력한 fluent API입니다.

4.1. Camel의 REST 개요

4.1.1. 개요

Apache Camel은 Camel 애플리케이션에서 REST 서비스를 정의하기 위한 다양한 접근 방식과 구성 요소를 제공합니다. 이 섹션에서는 이러한 다양한 접근 방식과 구성 요소에 대한 간략한 개요를 제공하여 요구 사항에 가장 적합한 구현 및 API를 결정할 수 있습니다.

4.1.2. REST는 무엇입니까?

REST( Representational State Transfer )는 GET,POST,PUT, DELETE 의 네 가지 기본 HTTP 동사만 사용하여 HTTP를 통해 데이터 전송을 중심으로 하는 분산 애플리케이션을 위한 아키텍처입니다.

HTTP를#159 메시지의 전송 프로토콜로 처리하는 Cryostat와 같은 프로토콜과 달리 REST 아키텍처는 HTTP를 직접 사용합니다. 주요 통찰력은 몇 가지 간단한 규칙에 의해 보강된 HTTP 프로토콜 자체는 분산 애플리케이션의 프레임워크 역할을 수행하기에 매우 적합합니다.

4.1.3. 샘플 REST 호출

REST 아키텍처는 표준 HTTP 동사를 기반으로 빌드되므로 대부분의 경우 일반 브라우저를 REST 클라이언트로 사용할 수 있습니다. 예를 들어 호스트와 포트 localhost:9091 에서 실행되는 간단한 Hello World REST 서비스를 호출하려면 브라우저에서 다음과 같은 URL로 이동할 수 있습니다.

http://localhost:9091/say/hello/Garp

그런 다음 Hello World REST 서비스는 다음과 같은 응답 문자열을 반환할 수 있습니다.

Hello Garp

브라우저 창에 표시됩니다. 표준 브라우저(또는 curl 명령줄 유틸리티)를 사용하지 않고 REST 서비스를 쉽게 호출할 수 있는 것은 REST 프로토콜이 빠르게 인기를 얻는 많은 이유 중 하나입니다.

4.1.4. REST 래퍼 계층

다음 REST 래퍼 계층은 REST 서비스를 정의하는 간단한 구문을 제공하며 다양한 REST 구현에 계층화할 수 있습니다.

REST DSL

REST DSL( camel-core)은 REST 서비스를 정의하는 간소화된 빌더 API를 제공하는 facade 또는 래퍼 계층입니다. REST DSL은 자체적으로 REST 구현을 제공하지 않습니다. 기본 REST 구현과 결합해야 합니다. 예를 들어 다음 Java 코드는 REST DSL을 사용하여 간단한 Hello World 서비스를 정의하는 방법을 보여줍니다.

rest("/say")
    .get("/hello/{name}").route().transform().simple("Hello ${header.name}");

자세한 내용은 4.2절. “REST DSL을 사용하여 서비스 정의” 에서 참조하십시오.

rest 구성 요소

Rest 구성 요소( camel-core)는 URI 구문을 사용하여 REST 서비스를 정의할 수 있는 래퍼 계층입니다. REST DSL과 마찬가지로 Rest 구성 요소는 자체적으로 REST 구현을 제공하지 않습니다. 기본 REST 구현과 결합해야 합니다.

HTTP 전송 구성 요소를 명시적으로 구성하지 않으면 REST DSL은 classpath에서 사용 가능한 구성 요소를 확인하여 사용할 HTTP 구성 요소를 자동으로 검색합니다. REST DSL은 모든 HTTP 구성 요소의 기본 이름을 찾고 찾은 첫 번째 구성 요소를 사용합니다. classpath에 HTTP 구성 요소가 없고 HTTP 전송을 명시적으로 구성하지 않은 경우 기본 HTTP 구성 요소는 camel-http 입니다.

참고

Camel 2.18에서 사용할 HTTP 구성 요소를 자동으로 검색하는 기능 Camel 2.17에서는 사용할 수 없습니다.

다음 Java 코드는 camel-rest 구성 요소를 사용하여 간단한 Hello World 서비스를 정의하는 방법을 보여줍니다.

from("rest:get:say:/hello/{name}").transform().simple("Hello ${header.name}");

4.1.5. REST 구현

Apache Camel은 다음 구성 요소를 통해 다양한 REST 구현을 제공합니다.

Spark-Rest 구성 요소

Spark-Rest 구성 요소( camel-spark-rest)는 URI 구문을 사용하여 REST 서비스를 정의할 수 있는 REST 구현입니다. Spark 프레임워크 자체는 Sinatra 프레임워크(Python API)를 기반으로 하는 Java API입니다. 예를 들어 다음 Java 코드는 Spark-Rest 구성 요소를 사용하여 간단한 Hello World 서비스를 정의하는 방법을 보여줍니다.

from("spark-rest:get:/say/hello/:name").transform().simple("Hello ${header.name}");

Rest 구성 요소와 달리 URI의 변수 구문은 {name} 대신 :name }입니다.

참고

Spark-Rest 구성 요소에는 Java 8이 필요합니다.

Restlet 구성 요소

Restlet 구성 요소( camel-restlet)는 기본적으로 서로 다른 전송 프로토콜 위에 계층화할 수 있는 REST 구현입니다(이 구성 요소는 HTTP 프로토콜에 대해서만 테스트됨). 또한 이 구성 요소는 Java에서 REST 서비스를 개발하기 위한 상용 프레임워크인 Restlet Framework 와의 통합을 제공합니다. 예를 들어 다음 Java 코드는 Restlet 구성 요소를 사용하여 간단한 Hello World 서비스를 정의하는 방법을 보여줍니다.

from("restlet:http://0.0.0.0:9091/say/hello/{name}?restletMethod=get")
    .transform().simple("Hello ${header.name}");

자세한 내용은 Apache Camel 구성 요소 참조 가이드의 Restlet 을 참조하십시오.

서블릿 구성 요소

Servlet 구성 요소( camel-servlet)는 Java 서블릿을 Camel 경로에 바인딩하는 구성 요소입니다. 즉, Servlet 구성 요소를 사용하면 표준 Java 서블릿인 것처럼 Camel 경로를 패키징하고 배포할 수 있습니다. 따라서 서블릿 구성 요소는 서블릿 컨테이너(예: Apache Tomcat HTTP 서버 또는 JBoss Enterprise Application Platform 컨테이너) 내에 Camel 경로를 배포해야 하는 경우 특히 유용합니다.

그러나 서블릿 구성 요소는 자체적으로 REST 서비스를 정의하기 위한 편리한 REST API를 제공하지 않습니다. 따라서 서블릿 구성 요소를 사용하는 가장 쉬운 방법은 사용자 친화적인 API로 REST 서비스를 정의할 수 있도록 REST DSL과 결합하는 것입니다.

자세한 내용은 Apache Camel 구성 요소 참조 가이드의 Servlet 을 참조하십시오.

4.1.6. Cryostat-RS REST 구현

Cryostat -RS ( RESTful Web Services에 대한 Java API)는 REST 요청을 Java 오브젝트에 바인딩하기 위한 프레임워크입니다. 이 프레임워크는 바인딩을 정의하기 위해 Java 클래스를 Cryostat-RS 주석으로 데코레이팅해야 합니다. Cryostat-RS 프레임워크는 비교적 성숙하며 REST 서비스 개발을 위한 정교한 프레임워크를 제공하지만, 프로그래밍은 다소 복잡합니다.

Apache Camel과의 Cryostat-RS 통합은 Apache CXF를 통해 계층화된 CXFRS 구성 요소에 의해 구현됩니다. 개요에서 Cryostat-RS는 다음 주석을 사용하여 Java 클래스에 REST 요청을 바인딩합니다. 이 주석은 사용 가능한 많은 주석의 불완전한 샘플일 뿐입니다.

@Path
Java 클래스에 컨텍스트 경로를 매핑하거나 하위 경로를 특정 Java 메서드에 매핑할 수 있는 주석입니다.
@GET, @POST, @PUT, @DELETE
HTTP 메서드를 Java 메서드에 매핑하는 주석입니다.
@PathParam
URI 매개변수를 Java 메서드 인수에 매핑하는 주석 또는 URI 매개변수를 필드에 삽입합니다.
@QueryParam
쿼리 매개변수를 Java 메서드 인수에 매핑하는 주석 또는 쿼리 매개변수를 필드에 삽입합니다.

REST 요청 또는 REST 응답의 본문은 일반적으로 XML(190) 데이터 형식이어야 합니다. 그러나 Apache CXF는 JSON 메시지도 구문 분석할 수 있도록 JSON 형식으로 JSON 형식의 변환을 지원합니다.

자세한 내용은 Apache Camel 구성 요소 참조 가이드 및 Apache CXF 개발 가이드 CXFRS 를 참조하십시오.

참고

CXFRS 구성 요소는 REST DSL과 통합 되지 않습니다.

4.2. REST DSL을 사용하여 서비스 정의

4.2.1. REST DSL은 facade입니다.

REST DSL은 효과적으로 Java DSL 또는 XML DSL(Domain Specific Language)에서 REST 서비스를 정의하기 위한 간소화된 구문을 제공하는 facade 입니다. REST DSL은 실제로 REST 구현을 제공하지 않으며, 기존 REST 구현에 대한 래퍼일 뿐입니다(Apache Camel에 여러 가지가 있음).

4.2.2. REST DSL의 이점

REST DSL 래퍼 계층은 다음과 같은 이점을 제공합니다.

  • REST 서비스를 정의하는 데 사용하기 쉬운 최신 구문입니다.
  • 여러 다른 Apache Camel 구성 요소와 호환됩니다.
  • OpenAPI 통합( camel-openapi-java 구성 요소를 통해).

4.2.3. REST DSL과 통합되는 구성 요소

REST DSL은 실제 REST 구현이 아니므로 가장 먼저 수행해야 하는 작업 중 하나는 기본 구현을 제공하기 위해 Camel 구성 요소를 선택하는 것입니다. 현재 다음 Camel 구성 요소가 REST DSL과 통합되어 있습니다.

참고

Rest 구성 요소( camel-core의 일부)는 REST 구현이 아닙니다. REST DSL과 마찬가지로 Rest 구성 요소는 facade이므로 URI 구문을 사용하여 REST 서비스를 정의하는 간단한 구문을 제공합니다. Rest 구성 요소에는 기본 REST 구현도 필요합니다.

4.2.4. REST 구현을 사용하도록 REST DSL 구성

REST 구현을 지정하려면 restConfiguration() 빌더(Java DSL) 또는 restConfiguration 요소( XML DSL)를 사용합니다. 예를 들어 Spark-Rest 구성 요소를 사용하도록 REST DSL을 구성하려면 Java DSL에서 다음과 같은 빌더 표현식을 사용합니다.

restConfiguration().component("spark-rest").port(9091);

XML DSL에서 다음과 같은 요소를 사용합니다( camelContext의 자식으로).

<restConfiguration component="spark-rest" port="9091"/>

4.2.5. 구문

REST 서비스를 정의하는 Java DSL 구문은 다음과 같습니다.

rest("BasePath").Option().
    .Verb("Path").Option().[to() | route().CamelRoute.endRest()]
    .Verb("Path").Option().[to() | route().CamelRoute.endRest()]
    ...
    .Verb("Path").Option().[to() | route().CamelRoute];

CamelRoute 는 선택적 임베디드 Camel 경로입니다(라이스에 표준 Java DSL 구문을 사용하여 정의됨).

REST 서비스 정의는 rest() 키워드로 시작한 다음 특정 URL 경로 세그먼트를 처리하는 하나 이상의 동사 절을 사용합니다. HTTP 동사는 get(), head(), put(), post(), delete(), patch() 또는 verb() 중 하나일 수 있습니다. 각 verb 절은 다음 구문 중 하나를 사용할 수 있습니다.

  • 동사 절은 () 키워드로 끝납니다. 예를 들면 다음과 같습니다.

    get("...").Option()+.to("...")
  • route() 키워드로 끝나는 동사 절( Camel 경로 포함용). 예를 들면 다음과 같습니다.

    get("...").Option()+.route("...").CamelRoute.endRest()

4.2.6. Java를 사용한 REST DSL

Java에서 REST DSL을 사용하여 서비스를 정의하려면 일반 Apache Camel 경로와 마찬가지로 RouteBuilder.configure() 메서드 본문에 REST 정의를 배치합니다. 예를 들어, Spark-Rest 구성 요소와 함께 REST DSL을 사용하여 간단한 Hello World 서비스를 정의하려면 다음 Java 코드를 정의합니다.

restConfiguration().component("spark-rest").port(9091);

rest("/say")
    .get("/hello").to("direct:hello")
    .get("/bye").to("direct:bye");

from("direct:hello")
    .transform().constant("Hello World");
from("direct:bye")
    .transform().constant("Bye World");

이전 예제에서는 세 가지 종류의 빌더를 제공합니다.

restConfiguration()
특정 REST 구현(Spark-Rest)을 사용하도록 REST DSL을 구성합니다.
rest()
REST DSL을 사용하여 서비스를 정의합니다. 각 verb 절은 들어오는 메시지를 직접 엔드포인트로 전달하는 to() 키워드로 종료됩니다( 직접 구성 요소는 동일한 애플리케이션 내에서 경로를 함께 분할).
from()
일반 Camel 경로를 정의합니다.

4.2.7. XML이 있는 REST DSL

XML에서 XML DSL을 사용하여 서비스를 정의하려면 rest 요소를 camelContext 요소의 자식으로 정의합니다. 예를 들어, Spark-Rest 구성 요소와 함께 REST DSL을 사용하여 간단한 Hello World 서비스를 정의하려면 다음 XML 코드( 블루프린트에서)를 정의합니다.

<camelContext xmlns="http://camel.apache.org/schema/blueprint">
  <restConfiguration component="spark-rest" port="9091"/>

  <rest path="/say">
    <get uri="/hello">
      <to uri="direct:hello"/>
    </get>
    <get uri="/bye">
      <to uri="direct:bye"/>
    </get>
  </rest>

  <route>
    <from uri="direct:hello"/>
    <transform>
      <constant>Hello World</constant>
    </transform>
  </route>
  <route>
    <from uri="direct:bye"/>
    <transform>
      <constant>Bye World</constant>
    </transform>
  </route>
</camelContext>

4.2.8. 기본 경로 지정

rest() 키워드(Java DSL) 또는 rest 요소의 path 속성( XML DSL)을 사용하면 기본 경로를 정의할 수 있으며, 기본 경로 앞에 모든 동사 절이 추가됩니다. 예를 들어 다음 Java DSL 조각이 제공됩니다.

rest("/say")
    .get("/hello").to("direct:hello")
    .get("/bye").to("direct:bye");

또는 다음 XML DSL 조각이 제공됩니다.

<rest path="/say">
  <get uri="/hello">
    <to uri="direct:hello"/>
  </get>
  <get uri="/bye" consumes="application/json">
    <to uri="direct:bye"/>
  </get>
</rest>

REST DSL 빌더는 다음과 같은 URL 매핑을 제공합니다.

/say/hello
/say/bye

기본 경로는 선택 사항입니다. 원하는 경우 각 동사 절에 전체 경로를 지정할 수 있습니다.

rest()
    .get("/say/hello").to("direct:hello")
    .get("/say/bye").to("direct:bye");

4.2.9. 동적 대상 사용

REST DSL은 toD 동적 매개 변수를 지원합니다. 이 매개변수를 사용하여 URI를 지정합니다.

예를 들어 JMS에서 동적 엔드포인트 URI는 다음과 같은 방식으로 정의할 수 있습니다.

public void configure() throws Exception {
   rest("/say")
     .get("/hello/{language}").toD("jms:queue:hello-${header.language}");
}

XML DSL에서 다음과 같은 세부 정보가 표시됩니다.

<rest uri="/say">
  <get uri="/hello//{language}">
    <toD uri="jms:queue:hello-${header.language}"/>
  </get>
<rest>

toD 동적 매개 변수에 대한 자세한 내용은 “동적 대상” 을 참조하십시오.

4.2.10. URI 템플릿

동사 인수에서는 이름이 지정된 속성( Camel 메시지 헤더에 매핑됨)에서 특정 경로 세그먼트를 캡처할 수 있는 URI 템플릿을 지정할 수 있습니다. 예를 들어 Hello World 애플리케이션을 이름별로 호출하도록 사용자 지정하려는 경우 다음과 같은 REST 서비스를 정의할 수 있습니다.

rest("/say")
    .get("/hello/{name}").to("direct:hello")
    .get("/bye/{name}").to("direct:bye");

from("direct:hello")
    .transform().simple("Hello ${header.name}");
from("direct:bye")
    .transform().simple("Bye ${header.name}");

URI 템플릿은 {name} 경로 세그먼트의 텍스트를 캡처하고 이 캡처된 텍스트를 이름 메시지 헤더에 복사합니다. /say/hello/Joe 로 끝나는 URL로 GET HTTP 요청을 전송하여 서비스를 호출하면 HTTP 응답은 Hello ctlplane 입니다.

4.2.11. 포함된 경로 구문

to() 키워드(Java DSL) 또는 to 요소( XML DSL)로 verb 절을 종료하는 대신 route() 키워드(Java DSL) 또는 경로 요소( XML DSL)를 사용하여 Apache Camel 경로를 REST DSL에 직접 포함할 수 있습니다. route() 키워드를 사용하면 다음 구문을 사용하여 동사 절에 경로를 포함할 수 있습니다.

RESTVerbClause.route("...").CamelRoute.endRest()

여기서 endRest() 키워드(Java DSL만 해당)는 동사 절을 분리할 수 있는 필수 문장 부호입니다( rest() 빌더에 두 개 이상의 동사 절이 있는 경우).

예를 들어 Java DSL에서 다음과 같이 포함된 Camel 경로를 사용하도록 Hello World 예제를 리팩터링할 수 있습니다.

rest("/say")
    .get("/hello").route().transform().constant("Hello World").endRest()
    .get("/bye").route().transform().constant("Bye World");

XML DSL의 예는 다음과 같습니다.

<camelContext xmlns="http://camel.apache.org/schema/blueprint">
  ...
  <rest path="/say">
    <get uri="/hello">
      <route>
        <transform>
          <constant>Hello World</constant>
        </transform>
      </route>
    </get>
    <get uri="/bye">
      <route>
        <transform>
          <constant>Bye World</constant>
        </transform>
      </route>
    </get>
  </rest>
</camelContext>
참고

현재 CamelContext 에서 예외 절( onException()) 또는 인터셉터( intercept()사용)를 정의하는 경우 이러한 exception 절과 인터셉터도 포함된 경로에서 활성화됩니다.

4.2.12. REST DSL 및 HTTP 전송 구성 요소

HTTP 전송 구성 요소를 명시적으로 구성하지 않으면 REST DSL은 classpath에서 사용 가능한 구성 요소를 확인하여 사용할 HTTP 구성 요소를 자동으로 검색합니다. REST DSL은 모든 HTTP 구성 요소의 기본 이름을 찾고 찾은 첫 번째 구성 요소를 사용합니다. classpath에 HTTP 구성 요소가 없고 HTTP 전송을 명시적으로 구성하지 않은 경우 기본 HTTP 구성 요소는 camel-http 입니다.

4.2.13. 요청 및 응답의 콘텐츠 유형 지정

consumes() 를 사용하여 HTTP 요청 및 응답의 콘텐츠 유형을 필터링하고 Java에서 () 옵션을 생성하거나 XML로 속성을 사용하고 생성할 수 있습니다. 예를 들어, 몇 가지 일반적인 콘텐츠 유형(알림적으로 인터넷 미디어 유형)은 다음과 같습니다.

  • text/plain
  • text/html
  • text/xml
  • application/json
  • application/xml

콘텐츠 유형은 REST DSL의 동사 절에 옵션으로 지정됩니다. 예를 들어, text/plain HTTP 요청만 수락하고 text/html HTTP 응답만 전송하도록 verb 절을 제한하려면 다음과 같은 Java 코드를 사용합니다.

rest("/email")
    .post("/to/{recipient}").consumes("text/plain").produces("text/html").to("direct:foo");

XML에서는 다음과 같이 사용 및 특성을 생성할 수 있습니다.

<camelContext xmlns="http://camel.apache.org/schema/blueprint">
  ...
  <rest path="/email">
    <post uri="/to/{recipient}" consumes="text/plain" produces="text/html">
      <to "direct:foo"/>
    </get>
  </rest>
</camelContext>

사용할 인수를 지정하거나 ( )를 쉼표 구분된 목록으로 지정할 수도 있습니다. 예를 들어 "text/plain, application/json"을 사용합니다.

4.2.14. 추가 HTTP 메서드

일부 HTTP 서버 구현은 추가 HTTP 메서드를 지원합니다. REST DSL의 표준 동사 세트인 get(), head(), put(), post(), delete(), patch(). 추가 HTTP 메서드에 액세스하려면 일반 키워드인 verb() 를 Java DSL 및 일반 요소인 verb 에서 XML DSL로 사용할 수 있습니다.

예를 들어 Java에서 TRACE HTTP 메서드를 구현하려면 다음을 수행합니다.

rest("/say")
    .verb("TRACE", "/hello").route().transform();

여기서 transform()IN 메시지의 본문을 OUT 메시지의 본문으로 복사하므로 HTTP 요청을 에코합니다.

XML에서 TRACE HTTP 메서드를 구현하려면 다음을 수행합니다.

<camelContext xmlns="http://camel.apache.org/schema/blueprint">
  ...
  <rest path="/say">
    <verb uri="/hello" method="TRACE">
      <route>
        <transform/>
      </route>
    </get>
</camelContext>

4.2.15. 사용자 정의 HTTP 오류 메시지 정의

REST 서비스에서 응답으로 오류 메시지를 보내야 하는 경우 다음과 같이 사용자 정의 HTTP 오류 메시지를 정의할 수 있습니다.

  1. Exchange.HTTP_RESPONSE_CODE 헤더 키를 오류 코드 값(예: 400,404 등)으로 설정하여 HTTP 오류 코드를 지정합니다. 이 설정은 일반 응답 대신 오류 메시지 응답을 보낼 REST DSL에 나타냅니다.
  2. 메시지 본문을 사용자 지정 오류 메시지로 채웁니다.
  3. 필요한 경우 Content-Type 헤더를 설정합니다.
  4. REST 서비스가 Java 오브젝트(즉, bindingMode 가 활성화됨)로 마샬링되도록 구성된 경우 skipBindingOnErrorCode 옵션이 활성화되어 있는지 확인해야 합니다(기본적으로). 이는 REST DSL이 응답을 전송할 때 메시지 본문을 분리하지 않도록 하기 위한 것입니다.

    오브젝트 바인딩에 대한 자세한 내용은 4.3절. “Java Objects 간에 마샬링” 을 참조하십시오.

다음 Java 예제에서는 사용자 정의 오류 메시지를 정의하는 방법을 보여줍니다.

// Java
// Configure the REST DSL, with JSON binding mode
restConfiguration().component("restlet").host("localhost").port(portNum).bindingMode(RestBindingMode.json);

// Define the service with REST DSL
rest("/users/")
    .post("lives").type(UserPojo.class).outType(CountryPojo.class)
        .route()
            .choice()
                .when().simple("${body.id} < 100")
                    .bean(new UserErrorService(), "idTooLowError")
                .otherwise()
                    .bean(new UserService(), "livesWhere");

이 예에서 입력 ID가 100보다 작으면 다음과 같이 구현된 UserErrorService pin을 사용하여 사용자 지정 오류 메시지를 반환합니다.

// Java
public class UserErrorService {
    public void idTooLowError(Exchange exchange) {
        exchange.getIn().setBody("id value is too low");
        exchange.getIn().setHeader(Exchange.CONTENT_TYPE, "text/plain");
        exchange.getIn().setHeader(Exchange.HTTP_RESPONSE_CODE, 400);
    }
}

UserErrorService pin에서 사용자 지정 오류 메시지를 정의하고 HTTP 오류 코드를 400 으로 설정합니다.

4.2.16. 매개변수 기본값

들어오는 Camel 메시지의 헤더에 기본값을 지정할 수 있습니다.

쿼리 매개변수에 대한 상세 정보와 같은 키워드를 사용하여 기본값을 지정할 수 있습니다. 예를 들어 아래 코드에서 기본값은 false 입니다. 즉, verbose 키가 있는 헤더에 다른 값이 제공되지 않으면 false 가 기본값으로 삽입됩니다.

rest("/customers/")
    .get("/{id}").to("direct:customerDetail")
    .get("/{id}/orders")
      .param()
	.name("verbose")
	.type(RestParamType.query)
	.defaultValue("false")
	.description("Verbose order details")
      .endParam()
        .to("direct:customerOrders")
    .post("/neworder").to("direct:customerNewOrder");

4.2.17. 사용자 지정 HTTP 오류 메시지에서 JsonParserException 래핑

사용자 지정 오류 메시지를 반환할 수 있는 일반적인 경우는 JsonParserException 예외를 래핑하기 위한 것입니다. 예를 들어 다음과 같이 Camel 예외 처리 메커니즘을 편리하게 악용하여 HTTP 오류 코드 400을 사용하여 사용자 정의 HTTP 오류 메시지를 생성할 수 있습니다.

// Java
onException(JsonParseException.class)
    .handled(true)
    .setHeader(Exchange.HTTP_RESPONSE_CODE, constant(400))
    .setHeader(Exchange.CONTENT_TYPE, constant("text/plain"))
    .setBody().constant("Invalid json data");

4.2.18. REST DSL 옵션

일반적으로 REST DSL 옵션은 다음과 같이 서비스 정의의 기본 부분(즉, 즉시 rest())에 직접 적용할 수 있습니다.

rest("/email").consumes("text/plain").produces("text/html")
    .post("/to/{recipient}").to("direct:foo")
    .get("/for/{username}").to("direct:bar");

이 경우 지정된 옵션은 모든 하위 동사 절에 적용됩니다. 또는 옵션은 다음과 같이 각 동사 절에 적용할 수 있습니다.

rest("/email")
    .post("/to/{recipient}").consumes("text/plain").produces("text/html").to("direct:foo")
    .get("/for/{username}").consumes("text/plain").produces("text/html").to("direct:bar");

지정된 옵션은 관련 동사 절에만 적용되는 경우 기본 부분의 설정을 재정의합니다.

표 4.1. “REST DSL 옵션” REST DSL에서 지원하는 옵션을 요약합니다.

표 4.1. REST DSL 옵션

Java DSLXML DSL설명

bindingMode()

@bindingMode

들어오는 메시지를 Java 오브젝트에 마샬링하는 데 사용할 수 있는 바인딩 모드를 지정합니다(선택적으로는 Java 개체를 발신 메시지에 매길 수 없음). can have the following values: off (default), auto,json,xml,json_xml.

consumes()

@consumes

동사 절은 HTTP 요청에서 지정된 인터넷 미디어 유형(MIME 유형)만 수락하도록 제한합니다. 일반적인 값은 text/plain,text/http,text/xml,application/json,application/xml 입니다.

customId()

@customId

Cryostat 관리를 위한 사용자 지정 ID를 정의합니다.

description()

description

REST 서비스 또는 동사 절을 문서화합니다. Cryostat 관리 및 툴링에 유용합니다.

enableCORS()

@enableCORS

true 인 경우 HTTP 응답에서 CORS(cross-origin resource sharing) 헤더를 활성화합니다. 기본값은 false 입니다.

id()

@id

REST 서비스의 고유 ID를 정의합니다. 이 ID는 Cryostat 관리 및 기타 툴링에 대해 정의하는 데 유용합니다.

method()

@method

이 동사 절에서 처리하는 HTTP 메서드를 지정합니다. 일반적으로 일반 동사 () 키워드와 함께 사용됩니다.

outType()

@outType

개체 바인딩이 활성화된 경우(즉, bindingMode 옵션이 활성화된 경우) 이 옵션은 HTTP 응답 메시지를 나타내는 Java 유형을 지정합니다.

produces()

생성

동사 절은 HTTP 응답에서 지정된 인터넷 미디어 유형(MIME 유형)만 생성하도록 제한합니다. 일반적인 값은 text/plain,text/http,text/xml,application/json,application/xml 입니다.

type()

@type

개체 바인딩이 활성화된 경우(즉, bindingMode 옵션이 활성화된 경우) 이 옵션은 HTTP Request 메시지를 나타내는 Java 유형을 지정합니다.

VerbURIArgument

@uri

경로 세그먼트 또는 URI 템플릿을 동사의 인수로 지정합니다. 예를 들어 get(VerbURIArgument) 입니다.

BasePathArgument

@path

rest() 키워드(Java DSL) 또는 나머지 요소( XML DSL)의 기본 경로를 지정합니다.

4.3. Java Objects 간에 마샬링

4.3.1. HTTP를 통한 전송을 위해 Java 오브젝트 마샬링

REST 프로토콜을 사용하는 가장 일반적인 방법 중 하나는 메시지 본문에 Java 빈의 내용을 전송하는 것입니다. 이 기능이 작동하려면 적절한 데이터 형식으로 Java 개체를 마샬링하는 메커니즘이 필요합니다. Java 오브젝트 인코딩에 적합한 다음 데이터 형식은 REST DSL에서 지원합니다.

JSON

JSON (JavaScript 개체 표기법)은 Java 오브젝트에 쉽게 매핑할 수 있는 경량 데이터 형식입니다. JSON 구문은 간결하고 쉽게 입력되며 사람이 읽고 쓸 수 있습니다. 이러한 모든 이유로 JSON은 REST 서비스의 메시지 형식으로 널리 사용되고 있습니다.

예를 들어 다음 JSON 코드는 속성 필드가 idname사용자 빈을 나타낼 수 있습니다.

{
    "id" : 1234,
    "name" : "Jane Doe"
}
JAXB

CryostatB (Java Architecture for XML Binding)는 Java 오브젝트에 쉽게 매핑할 수 있는 XML 기반 데이터 형식입니다. XML을 Java 객체로 마샬링하려면 사용하려는 Java 클래스에도 주석을 달아야 합니다.

예를 들어 다음 CryostatB 코드는 속성 필드 idname 이라는 두 개의 속성 필드가 있는 User VLAN을 나타낼 수 있습니다.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<User>
  <Id>1234</Id>
  <Name>Jane Doe</Name>
</User>
참고

Camel 2.17.0에서 CryostatB 데이터 형식 및 유형 변환기는 Cryostat Root Cryostat 대신 ObjectFactory 를 사용하는 클래스의 XML에서 Cryostat로 변환을 지원합니다. 또한 camel 컨텍스트에는 값이 true인 CamelJaxbObjectFactory 속성이 포함되어야 합니다. 그러나 최적화로 인해 기본값은 false입니다.

4.3.2. REST DSL과 JSON 및 CryostatB 통합

물론 메시지 본문을 Java 개체로 변환하거나 직접 변환하는 데 필요한 코드를 작성할 수 있습니다. 그러나 REST DSL은 이러한 변환을 자동으로 수행할 수 있는 편의성을 제공합니다. 특히 JSON 및 CryostatB와 REST DSL을 통합하면 다음과 같은 이점이 있습니다.

  • Java 개체까지 마샬링이 자동으로 수행됩니다(적절한 구성).
  • REST DSL은 데이터 형식(JSON 또는 CryostatB)을 자동으로 감지하고 적절한 변환을 수행할 수 있습니다.
  • REST DSL은 추상화 계층 을 제공하므로 작성하는 코드는 특정 JSON 또는 CryostatB 구현에 국한되지 않습니다. 따라서 나중에 구현을 전환하여 애플리케이션 코드에 최소한의 영향을 미칠 수 있습니다.

4.3.3. 지원되는 데이터 형식 구성 요소

Apache Camel은 JSON 및 CryostatB 데이터 형식의 다양한 구현을 제공합니다. 다음 데이터 형식은 현재 REST DSL에서 지원합니다.

  • JSON

    • jackson 데이터 형식 (camel-jackson) (기본값)
    • gson 데이터 형식 (camel-gson)
    • XStream 데이터 형식(camel-xstream)
  • JAXB

    • CryostatB 데이터 형식(camel-jaxb)

4.3.4. 개체 마샬링 활성화 방법

REST DSL에서 오브젝트 마샬링을 활성화하려면 다음 사항을 관찰합니다.

  1. bindingMode 옵션을 설정하여 바인딩 모드를 활성화합니다. 바인딩 모드를 설정할 수 있는 여러 수준이 있습니다. 자세한 내용은 “바인딩 모드 구성”을 참조하십시오.
  2. type 옵션(필수)과 outType 옵션(선택 사항)을 사용하여 들어오는 메시지에서 변환할 Java 유형을 지정합니다(선택 사항).
  3. Java 오브젝트를 CryostatB 데이터 형식으로 변환하려면 적절한 CryostatB 주석으로 Java 클래스에 주석을 답니다.
  4. restConfiguration 빌더에 지정할 수 있는 jsonDataFormat 옵션 및/또는 xmlDataFormat 옵션을 사용하여 기본 데이터 형식 구현(또는 구현)을 지정합니다.
  5. 경로에서 반환 값을 제공하는 경우 일반적으로 교환 본문의 Out 메시지를 CryostatB 주석이 있는 클래스의 인스턴스로 설정해야 합니다. 그러나 XML 형식으로 직접 CryostatB 반환 값을 제공하려는 경우 dataFormatProperty 를 key, xml.out.mustBeJAXB Cryostat , false 로 설정합니다( restConfiguration 빌더에 지정할 수 있음). 예를 들어 XML DSL 구문에서 다음을 수행합니다.

    <restConfiguration ...>
      <dataFormatProperty key="xml.out.mustBeJAXBElement"
                          value="false"/>
      ...
    </restConfiguration>
  6. 프로젝트 빌드 파일에 필요한 종속 항목을 추가합니다. 예를 들어 Maven 빌드 시스템을 사용하고 Jackson 데이터 형식을 사용하는 경우 Maven POM 파일에 다음 종속성을 추가합니다.

    <?xml version="1.0" encoding="UTF-8"?>
    <project ...>
      ...
      <dependencies>
        ...
        <!-- use for json binding --> <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-jackson</artifactId> </dependency>
        ...
      </dependencies>
    </project>
  7. OSGi 컨테이너에 애플리케이션을 배포할 때 선택한 데이터 형식에 필요한 기능을 설치해야 합니다. 예를 들어 jackson 데이터 형식(기본값)을 사용하는 경우 다음 Karaf console 명령을 입력하여 camel-jackson 기능을 설치합니다.

    JBossFuse:karaf@root> features:install camel-jackson

    또는 Fabric 환경에 배포하는 경우 Fabric 프로필에 기능을 추가합니다. 예를 들어 프로필 MyRestProfile 을 사용하는 경우 다음 console 명령을 입력하여 기능을 추가할 수 있습니다.

    JBossFuse:karaf@root> fabric:profile-edit --features camel-jackson MyRestProfile

4.3.5. 바인딩 모드 구성

bindingMode 옵션은 기본적으로 꺼져 있으므로 Java 개체를 마샬링할 수 있도록 명시적으로 구성해야 합니다. Cryostat에는 지원되는 바인딩 모드 목록이 표시됩니다.

참고

Camel 2.16.3부터 JSon/JAXB로의 바인딩 이후 content-type 헤더에 json 또는 xml 가 포함된 경우에만 발생합니다. 이를 통해 메시지 본문을 바인딩을 사용하여 마샬링하지 않아야 하는 경우 사용자 정의 콘텐츠 유형을 지정할 수 있습니다. 예를 들어 메시지 본문이 사용자 지정 바이너리 페이로드인 경우 유용합니다.

표 4.2. REST DSL BInding 모드

바인딩 모드설명

off

바인딩이 꺼져 있습니다 (기본값)입니다.

auto

JSON 및/또는 XML에 대한 바인딩이 활성화됩니다. 이 모드에서 Camel은 들어오는 메시지의 형식에 따라 JSON 또는 XML(JAXB)을 자동으로 선택합니다. 두 종류의 데이터 형식을 모두 활성화할 필요는 없지만 JSON 구현, XML 구현 또는 둘 다 클래스 경로에 제공할 수 있습니다.

json

JSON에만 바인딩이 활성화됩니다. 클래스 경로에 JSON 구현을 제공해야 합니다 (기본적으로 Camel은 camel-jackson 구현을 활성화하려고 시도합니다).

xml

XML에만 바인딩이 활성화됩니다. 클래스 경로에 XML 구현을 제공해야 합니다 (기본적으로 Camel이 camel-jaxb 구현을 사용하려고 함).

json_xml

JSON 및 XML 모두에 바인딩이 활성화됩니다. 이 모드에서 Camel은 들어오는 메시지의 형식에 따라 JSON 또는 XML(JAXB)을 자동으로 선택합니다. 클래스 경로에 두 종류의 데이터 형식을 모두 제공해야 합니다.

Java에서 이러한 바인딩 모드 값은 다음 열거 유형의 인스턴스로 표시됩니다.

org.apache.camel.model.rest.RestBindingMode

다음과 같이 bindingMode 를 설정할 수 있는 여러 가지 수준이 있습니다.

REST DSL 구성

다음과 같이 restConfiguration 빌더에서 bindingMode 옵션을 설정할 수 있습니다.

restConfiguration().component("servlet").port(8181).bindingMode(RestBindingMode.json);
서비스 정의 기본 부분

다음과 같이 rest() 키워드( verb 절 전) 다음에 즉시 bindingMode 옵션을 설정할 수 있습니다.

rest("/user").bindingMode(RestBindingMode.json).get("/{id}").VerbClause
verb 절

다음과 같이 verb 절에서 bindingMode 옵션을 설정할 수 있습니다.

rest("/user")
    .get("/{id}").bindingMode(RestBindingMode.json).to("...");

4.3.6. 예제

서블릿 구성 요소를 REST 구현으로 사용하여 REST DSL을 사용하는 방법을 보여주는 전체 코드 예제를 보려면 Apache Camel camel-example-servlet-rest-blueprint 예제를 살펴보십시오. 이 예제는 Fuse 설치의 extras/ 하위 디렉터리에 제공되는 독립 실행형 Apache Camel 배포 apache-camel-2.23.2.fuse-790054-redhat-00001.zip 을 설치하여 찾을 수 있습니다.

독립 실행형 Apache Camel 배포를 설치한 후 다음 디렉터리에서 예제 코드를 찾을 수 있습니다.

ApacheCamelInstallDir/examples/camel-example-servlet-rest-blueprint

4.3.7. Servlet 구성 요소를 REST 구현으로 구성

camel-example-servlet-rest-blueprint 예제에서 REST DSL의 기본 구현은 Servlet 구성 요소에서 제공합니다. 서블릿 구성 요소는 예 4.1. “REST DSL을 위한 서블릿 구성 요소 구성” 에 표시된 것처럼 블루프린트 XML 파일에 구성됩니다.

예 4.1. REST DSL을 위한 서블릿 구성 요소 구성

<?xml version="1.0" encoding="UTF-8"?>
<blueprint ...>

  <!-- to setup camel servlet with OSGi HttpService -->
  <reference id="httpService" interface="org.osgi.service.http.HttpService"/>

  <bean class="org.apache.camel.component.servlet.osgi.OsgiServletRegisterer"
        init-method="register"
        destroy-method="unregister">
    <property name="alias" value="/camel-example-servlet-rest-blueprint/rest"/>
    <property name="httpService" ref="httpService"/>
    <property name="servlet" ref="camelServlet"/>
  </bean>

  <bean id="camelServlet" class="org.apache.camel.component.servlet.CamelHttpTransportServlet"/>
  ...
  <camelContext xmlns="http://camel.apache.org/schema/blueprint">

    <restConfiguration component="servlet"
                       bindingMode="json"
                       contextPath="/camel-example-servlet-rest-blueprint/rest"
                       port="8181">
      <dataFormatProperty key="prettyPrint" value="true"/>
    </restConfiguration>
    ...
  </camelContext>

</blueprint>

REST DSL을 사용하여 Servlet 구성 요소를 구성하려면 다음 세 계층으로 구성된 스택을 구성해야 합니다.

REST DSL 계층
REST DSL 계층은 component 속성을 값인 서블릿 으로 설정하여 Servlet 구성 요소와 통합되는 restConfiguration 요소로 구성됩니다.
서블릿 구성 요소 계층
Servlet 구성 요소 계층은 클래스 인스턴스인 CamelHttpTransportServlet 의 인스턴스로 구현됩니다. 여기서 example 인스턴스에 빈 ID인 camelServlet.
HTTP 컨테이너 계층

서블릿 구성 요소는 HTTP 컨테이너에 배포해야 합니다. Karaf 컨테이너는 일반적으로 포트 8181 포트에서 HTTP 요청을 수신 대기하는 기본 HTTP 컨테이너(a Cryostatty HTTP 컨테이너)로 구성됩니다. Servlet 구성 요소를 기본 Cryostatty 컨테이너에 배포하려면 다음을 수행해야 합니다.

  1. org.osgi.service.http.HttpService OSGi 서비스에 대한 OSGi 참조를 가져옵니다. 이 서비스는 OSGi의 기본 HTTP 서버에 대한 액세스를 제공하는 표준 OSGi 인터페이스입니다.
  2. 유틸리티 클래스인 OsgiServletRegisterer 인스턴스를 생성하여 HTTP 컨테이너에 Servlet 구성 요소를 등록합니다. OsgiServletRegisterer 클래스는 Servlet 구성 요소의 라이프사이클 관리를 단순화하는 유틸리티입니다. 이 클래스의 인스턴스가 생성되면 Cryostat Service OSGi 서비스에서 registerServlet 메서드를 자동으로 호출하고 인스턴스가 삭제되면 unregister 메서드를 자동으로 호출합니다.

4.3.8. 필수 종속 항목

이 예제에는 다음과 같이 REST DSL에 중요한 두 가지 종속성이 있습니다.

서블릿 구성 요소

REST DSL의 기본 구현을 제공합니다. Maven POM 파일에 다음과 같이 지정됩니다.

<dependency>
  <groupId>org.apache.camel</groupId>
  <artifactId>camel-servlet</artifactId>
  <version>${camel-version}</version>
</dependency>

또한 OSGi 컨테이너에 애플리케이션 번들을 배포하기 전에 다음과 같이 서블릿 구성 요소 기능을 설치해야 합니다.

JBossFuse:karaf@root> features:install camel-servlet
jackson 데이터 형식

JSON 데이터 형식 구현을 제공합니다. Maven POM 파일에 다음과 같이 지정됩니다.

<dependency>
  <groupId>org.apache.camel</groupId>
  <artifactId>camel-jackson</artifactId>
  <version>${camel-version}</version>
</dependency>

또한 OSGi 컨테이너에 애플리케이션 번들을 배포하기 전에 다음과 같이 Jackson 데이터 형식 기능을 설치해야 합니다.

JBossFuse:karaf@root> features:install camel-jackson

4.3.9. 응답을 위한 Java 유형

예제 애플리케이션은 HTTP 요청 및 응답 메시지에서 User 유형 오브젝트를 다시 전달합니다. 사용자 Java 클래스는 예 4.2. “JSON 응답을 위한 사용자 클래스” 에 표시된 대로 정의됩니다.

예 4.2. JSON 응답을 위한 사용자 클래스

// Java
package org.apache.camel.example.rest;

public class User {

    private int id;
    private String name;

    public User() {
    }

    public User(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

User 클래스는 JSON 데이터 형식에서 비교적 간단한 표현입니다. 예를 들어 JSON 형식으로 표시된 이 클래스의 일반적인 인스턴스는 다음과 같습니다.

{
    "id" : 1234,
    "name" : "Jane Doe"
}

4.3.10. JSON 바인딩이 있는 샘플 REST DSL 경로

이 예제의 REST DSL 구성 및 REST 서비스 정의는 예 4.3. “JSON 바인딩을 사용하는 REST DSL 경로” 에 표시됩니다.

예 4.3. JSON 바인딩을 사용하는 REST DSL 경로

<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           ...>
  ...
  <!-- a bean for user services -->
  <bean id="userService" class="org.apache.camel.example.rest.UserService"/>

  <camelContext xmlns="http://camel.apache.org/schema/blueprint">

    <restConfiguration component="servlet"
                       bindingMode="json"
                       contextPath="/camel-example-servlet-rest-blueprint/rest"
                       port="8181">
      <dataFormatProperty key="prettyPrint" value="true"/>
    </restConfiguration>

    <!-- defines the REST services using the  base path, /user -->
    <rest path="/user" consumes="application/json" produces="application/json">
      <description>User rest service</description>

      <!-- this is a rest GET to view a user with the given id -->
      <get uri="/{id}" outType="org.apache.camel.example.rest.User">
        <description>Find user by id</description>
        <to uri="bean:userService?method=getUser(${header.id})"/>
      </get>

      <!-- this is a rest PUT to create/update a user -->
      <put type="org.apache.camel.example.rest.User">
        <description>Updates or create a user</description>
        <to uri="bean:userService?method=updateUser"/>
      </put>

      <!-- this is a rest GET to find all users -->
      <get uri="/findAll" outType="org.apache.camel.example.rest.User[]">
        <description>Find all users</description>
        <to uri="bean:userService?method=listUsers"/>
      </get>

    </rest>

  </camelContext>

</blueprint>

4.3.11. REST 작업

예 4.3. “JSON 바인딩을 사용하는 REST DSL 경로” 의 REST 서비스는 다음 REST 작업을 정의합니다.

GET /camel-example-servlet-rest-blueprint/rest/user/{id}
{id} 에서 식별한 사용자의 세부 정보를 가져옵니다. 여기서 HTTP 응답이 JSON 형식으로 반환됩니다.
PUT /camel-example-servlet-rest-blueprint/rest/user
사용자 세부 정보가 JSON 형식으로 인코딩되는 PUT 메시지의 본문에 포함된 새 사용자를 생성합니다( 사용자 오브젝트 유형과 일치).
GET /camel-example-servlet-rest-blueprint/rest/user/findAll
HTTP 응답이 사용자 배열로 반환되는 모든 사용자에 대한 세부 정보를 JSON 형식으로 가져옵니다.

4.3.12. REST 서비스를 호출할 URL

예 4.3. “JSON 바인딩을 사용하는 REST DSL 경로” 에서 REST DSL 정의를 검사하여 각 REST 작업을 호출하는 데 필요한 URL을 통합할 수 있습니다. 예를 들어 지정된 ID가 있는 사용자의 세부 정보를 반환하는 첫 번째 REST 작업을 호출하려면 URL은 다음과 같이 빌드됩니다.

http://localhost:8181
restConfiguration 에서 프로토콜은 기본적으로 http 로 설정되고 포트는 명시적으로 8181 로 설정됩니다.
/camel-example-servlet-rest-blueprint/rest
restConfiguration 요소의 contextPath 속성에 의해 지정됩니다.
/user
rest 요소의 경로 특성에 따라 지정됩니다.
/{id}
get verb 요소의 uri 속성으로 지정됩니다.

따라서 명령줄에서 다음 명령을 입력하여 curl 유틸리티를 사용하여 이 REST 작업을 호출할 수 있습니다.

curl -X GET -H "Accept: application/json" http://localhost:8181/camel-example-servlet-rest-blueprint/rest/user/123

마찬가지로 다음 샘플 명령을 입력하여 curl 을 사용하여 나머지 REST 작업을 호출할 수 있습니다.

curl -X GET -H "Accept: application/json" http://localhost:8181/camel-example-servlet-rest-blueprint/rest/user/findAll

curl -X PUT -d "{ \"id\": 666, \"name\": \"The devil\"}" -H "Accept: application/json" http://localhost:8181/camel-example-servlet-rest-blueprint/rest/user

4.4. REST DSL 구성

4.4.1. Java로 구성

Java에서는 restConfiguration() 빌더 API를 사용하여 REST DSL을 구성할 수 있습니다. 예를 들어 Servlet 구성 요소를 기본 구현으로 사용하도록 REST DSL을 구성하려면 다음을 수행합니다.

restConfiguration().component("servlet").bindingMode("json").port("8181")
    .contextPath("/camel-example-servlet-rest-blueprint/rest");

4.4.2. XML로 구성

XML에서는 restConfiguration 요소를 사용하여 REST DSL을 구성할 수 있습니다. 예를 들어 Servlet 구성 요소를 기본 구현으로 사용하도록 REST DSL을 구성하려면 다음을 수행합니다.

<?xml version="1.0" encoding="UTF-8"?>
<blueprint ...>
  ...
  <camelContext xmlns="http://camel.apache.org/schema/blueprint">
    ...
    <restConfiguration component="servlet"
                       bindingMode="json"
                       contextPath="/camel-example-servlet-rest-blueprint/rest"
                       port="8181">
      <dataFormatProperty key="prettyPrint" value="true"/>
    </restConfiguration>
    ...
  </camelContext>

</blueprint>

4.4.3. 구성 옵션

표 4.3. “REST DSL 구성 옵션” restConfiguration() 빌더(Java DSL) 또는 restConfiguration 요소(XML DSL)를 사용하여 REST DSL을 구성하는 옵션을 표시합니다.

표 4.3. REST DSL 구성 옵션

Java DSLXML DSL설명

component()

@component

REST 전송으로 사용할 Camel 구성 요소(예: 서블릿 ,restlet ,spark-rest 등)를 지정합니다. 값은 사용자 지정 인스턴스의 표준 구성 요소 이름 또는 빈 ID일 수 있습니다. 이 옵션을 지정하지 않으면 Camel은 classpath 또는 Cryostat 레지스트리에서 RestConsumerFactory 인스턴스를 찾습니다.

scheme()

@scheme

REST 서비스를 노출하는 데 사용할 프로토콜입니다. 기본 REST 구현에 따라 다르지만 일반적으로 httphttps 가 지원됩니다. 기본값은 http 입니다.

host()

@host

REST 서비스를 노출하는 데 사용할 호스트 이름입니다.

port()

@port

REST 서비스를 노출하는 데 사용할 포트 번호입니다.

참고: 이 설정은 컨테이너의 표준 HTTP 포트를 대신 사용하는 서블릿 구성 요소에서 무시됩니다. Apache Karaf OSGi 컨테이너의 경우 표준 HTTP 포트는 일반적으로 8181입니다. Cryostat 및 툴링을 위해 포트 값을 설정하는 것이 좋습니다.

contextPath()

@contextPath

REST 서비스의 선행 컨텍스트 경로를 설정합니다. 배포된 웹 애플리케이션이 컨텍스트 경로 설정을 사용하여 배포되는 Servlet과 같은 구성 요소와 함께 사용할 수 있습니다.

hostNameResolver()

@hostNameResolver

호스트 이름이 명시적으로 설정되지 않은 경우 이 확인자는 REST 서비스의 호스트를 결정합니다. 가능한 값은 RestHostNameResolver.localHostName (Java DSL) 또는 localHostName ( XML DSL) 또는 호스트 이름 형식으로 해석되는 및 RestHostNameResolver.localIp (Java DSL) 또는 localIp (SDN DSL)로 해석되어 점으로 해석되는 10진수 IP 주소 형식으로 확인됩니다. Camel 2.17 RestHostNameResolver.allLocalIp 를 사용하여 모든 로컬 IP 주소로 확인할 수 있습니다.

기본값은 Camel 2.16까지 localHostName 입니다. Camel 2.17에서 기본값은 allLocalIp 입니다.

bindingMode()

@bindingMode

JSON 또는 XML 형식 메시지에 대한 바인딩 모드를 활성화합니다. 가능한 값은 off,auto json,xml, 또는 json_xml 입니다. 기본값은 OFF 입니다.

skipBindingOnErrorCode()

@skipBindingOnErrorCode

사용자 정의 HTTP 오류 코드 헤더가 있는 경우 출력에서 바인딩을 건너뛸지 여부를 지정합니다. 이렇게 하면 성공적인 메시지가 수행되므로 JSON 또는 XML에 바인딩되지 않는 사용자 지정 오류 메시지를 빌드할 수 있습니다. 기본값은 true 입니다.

enableCORS()

@enableCORS

true 인 경우 HTTP 응답에서 CORS(cross-origin resource sharing) 헤더를 활성화합니다. 기본값은 false 입니다.

jsonDataFormat()

@jsonDataFormat

Camel이 JSON 데이터 형식을 구현하는 데 사용하는 구성 요소를 지정합니다. 가능한 값은 json-jackson,json-gson,json-xstream 입니다. 기본값은 json-jackson 입니다.

xmlDataFormat()

@xmlDataFormat

Camel이 XML 데이터 형식을 구현하는 데 사용하는 구성 요소를 지정합니다. 가능한 값은 jaxb 입니다. 기본값은 jaxb 입니다.

componentProperty()

componentProperty

기본 REST 구현에서 임의의 구성 요소 수준 속성을 설정할 수 있습니다.

endpointProperty()

endpointProperty

기본 REST 구현에서 임의의 엔드포인트 수준 속성을 설정할 수 있습니다.

consumerProperty()

consumerProperty

기본 REST 구현에서 임의의 소비자 엔드포인트 속성을 설정할 수 있습니다.

dataFormatProperty()

dataFormatProperty

기본 데이터 형식 구성 요소(예: jackson 또는 CryostatB)에서 임의의 속성을 설정할 수 있습니다. Camel 2.14.1 이후부터는 다음 접두사를 속성 키에 연결할 수 있습니다.

  • json.in
  • json.out
  • xml.in
  • xml.out

속성 설정을 특정 형식 유형(JSON 또는 XML) 및 특정 메시지 방향(IN 또는 OUT)으로 제한하려면 다음을 수행합니다.

corsHeaderProperty()

corsHeaders

사용자 지정 CORS 헤더를 키/값 쌍으로 지정할 수 있습니다.

4.4.4. 기본 CORS 헤더

CORS(cross-origin resource sharing)가 활성화된 경우 다음 헤더가 기본적으로 설정됩니다. 선택적으로 corsHeaderProperty DSL 명령을 호출하여 기본 설정을 덮어쓸 수 있습니다.

표 4.4. 기본 CORS 헤더

헤더 키헤더 값

access-Control-Allow-Origin

\*

access-Control-Allow-Methods

GET,HEAD,POST,PUT,DELETE,TRACE,OPTIONS,CONNECT,PATCH

access-Control-Allow-Headers

origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers

access-Control-Max-Age

3600

4.4.5. jackson JSON 기능 활성화 또는 비활성화

dataFormatProperty 옵션에서 다음 키를 구성하여 특정 Jackson JSON 기능을 활성화하거나 비활성화할 수 있습니다.

  • json.in.disableFeatures
  • json.in.enableFeatures

예를 들어 Jackson의 FAIL_ON_UNKNOWN_PROPERTIES 기능을 비활성화하려면 JSON 입력에 Java 오브젝트에 매핑할 수 없는 속성이 있는 경우 Jackson이 실패합니다.

restConfiguration().component("jetty")
    .host("localhost").port(getPort())
    .bindingMode(RestBindingMode.json)
    .dataFormatProperty("json.in.disableFeatures", "FAIL_ON_UNKNOWN_PROPERTIES");

쉼표로 구분된 목록을 지정하여 여러 기능을 비활성화할 수 있습니다. 예를 들면 다음과 같습니다.

.dataFormatProperty("json.in.disableFeatures", "FAIL_ON_UNKNOWN_PROPERTIES,ADJUST_DATES_TO_CONTEXT_TIME_ZONE");

다음은 Java DSL에서 jackson JSON 기능을 비활성화하고 활성화하는 방법을 보여주는 예입니다.

restConfiguration().component("jetty")
    .host("localhost").port(getPort())
    .bindingMode(RestBindingMode.json)
    .dataFormatProperty("json.in.disableFeatures", "FAIL_ON_UNKNOWN_PROPERTIES,ADJUST_DATES_TO_CONTEXT_TIME_ZONE")
    .dataFormatProperty("json.in.enableFeatures", "FAIL_ON_NUMBERS_FOR_ENUMS,USE_BIG_DECIMAL_FOR_FLOATS");

다음은 XML DSL에서 jackson JSON 기능을 비활성화하고 활성화하는 방법을 보여주는 예입니다.

<restConfiguration component="jetty" host="localhost" port="9090" bindingMode="json">
  <dataFormatProperty key="json.in.disableFeatures" value="FAIL_ON_UNKNOWN_PROPERTIES,ADJUST_DATES_TO_CONTEXT_TIME_ZONE"/>
  <dataFormatProperty key="json.in.enableFeatures" value="FAIL_ON_NUMBERS_FOR_ENUMS,USE_BIG_DECIMAL_FOR_FLOATS"/>
</restConfiguration>

비활성화하거나 활성화할 수 있는 Jackson 기능은 다음 Jackson 클래스의 enum ID에 해당합니다.

4.5. OpenAPI 통합

4.5.1. 개요

OpenAPI 서비스를 사용하여 CamelContext 파일에서 REST 정의 경로 및 엔드포인트에 대한 API 문서를 생성할 수 있습니다. 이렇게 하려면 Java 기반인 camel-openapi-java 모듈과 함께 Camel REST DSL을 사용합니다. camel-openapi-java 모듈은 CamelContext와 통합된 서블릿을 생성하고 각 REST 끝점에서 정보를 가져와서 JSON 또는 YAML 형식의 API 문서를 생성합니다.

Maven을 사용하는 경우 pom.xml 파일을 편집하여 camel-openapi-java 구성 요소에 대한 종속성을 추가합니다.

<dependency>
   <groupId>org.apache.camel</groupId>
   <artifactId>camel-openapi-java</artifactId>
   <version>x.x.x</version>
   <!-- Specify the version of your camel-core module. -->
</dependency>

4.5.2. OpenAPI를 사용하도록 CamelContext 구성

Camel REST DSL에서 OpenAPI를 사용할 수 있도록 apiContextPath() 를 호출하여 OpenAPI 생성 API 문서의 컨텍스트 경로를 설정합니다. 예를 들면 다음과 같습니다.

public class UserRouteBuilder extends RouteBuilder {
    @Override
    public void configure() throws Exception {
        // Configure the Camel REST DSL to use the netty4-http component:
        restConfiguration().component("netty4-http").bindingMode(RestBindingMode.json)
            // Generate pretty print output:
            .dataFormatProperty("prettyPrint", "true")
            // Set the context path and port number that netty will use:
            .contextPath("/").port(8080)
            // Add the context path for the OpenAPI-generated API documentation:
            .apiContextPath("/api-doc")
                .apiProperty("api.title", "User API").apiProperty("api.version", "1.2.3")
                // Enable CORS:
                .apiProperty("cors", "true");

        // This user REST service handles only JSON files:
        rest("/user").description("User rest service")
            .consumes("application/json").produces("application/json")
            .get("/{id}").description("Find user by id").outType(User.class)
                .param().name("id").type(path).description("The id of the user to get").dataType("int").endParam()
                .to("bean:userService?method=getUser(${header.id})")
            .put().description("Updates or create a user").type(User.class)
                .param().name("body").type(body).description("The user to update or create").endParam()
                .to("bean:userService?method=updateUser")
            .get("/findAll").description("Find all users").outTypeList(User.class)
                .to("bean:userService?method=listUsers");
    }
}

4.5.3. OpenAPI 모듈 구성 옵션

아래 표에 설명된 옵션을 사용하여 OpenAPI 모듈을 구성할 수 있습니다. 다음과 같이 옵션을 설정합니다.

  • camel-openapi-java 모듈을 서블릿으로 사용하는 경우 web.xml 파일을 업데이트하고 설정할 각 구성 옵션에 init-param 요소를 지정하여 옵션을 설정합니다.
  • Camel REST 구성 요소에서 camel-openapi-java 모듈을 사용하는 경우 enableCORS(), host() 또는 contextPath() 와 같은 적절한 RestConfigurationDefinition 메서드를 호출하여 옵션을 설정합니다. RestConfigurationDefinition.apiProperty() 메서드를 사용하여 api.xxx 옵션을 설정합니다.
옵션유형설명

api.contact.email

문자열

API 관련 서신에 사용할 이메일 주소입니다.

api.contact.name

문자열

연결할 사람 또는 조직의 이름입니다.

api.contact.url

문자열

자세한 내용은 웹 사이트에 대한 URL입니다.

apiContextIdListing

부울

애플리케이션이 두 개 이상의 CamelContext 오브젝트를 사용하는 경우 기본 동작은 현재 CamelContext 에서만 REST 끝점을 나열하는 것입니다. REST 서비스를 실행 중인 JVM에서 실행 중인 각 CamelContext 의 REST 끝점 목록을 보려면 이 옵션을 true로 설정합니다. apiContextIdListing 이 true인 경우 OpenAPI는 /api-docs 와 같은 루트 경로에 CamelContext ID를 JSON 형식의 이름 목록으로 출력합니다. OpenAPI 생성 설명서에 액세스하려면 REST 컨텍스트 경로를 CamelContext ID(예: api-docs/myCamel )에 추가합니다. apiContextIdPattern 옵션을 사용하여 이 출력 목록의 이름을 필터링할 수 있습니다.

apiContextIdPattern

문자열

컨텍스트 목록에 CamelContext ID를 필터링하는 패턴입니다. 정규식을 지정하고 *를 와일드카드로 사용할 수 있습니다. 이는 Camel Intercept 기능에서 사용하는 것과 동일한 패턴 일치 기능입니다.

api.license.name

문자열

API에 사용되는 라이센스 이름입니다.

api.license.url

문자열

API에 사용되는 라이센스의 URL입니다.

api.path

문자열

문서를 생성할 REST API를 사용할 수 있는 경로를 설정합니다(예: /api-docs ). 상대 경로를 지정합니다. (예: http 또는 https )는 지정하지 마십시오. camel-openapi-java 모듈은 이 형식의 런타임 시 절대 경로를 계산합니다. protocol://host:port/context-path/api-path.

api.termsOfService

문자열

API 서비스 조건에 대한 URL입니다.

api.title

문자열

애플리케이션 이름입니다.

api.version

문자열

API 버전입니다. 기본값은 0.0.0입니다.

base.path

문자열

필수 항목입니다. REST 서비스를 사용할 수 있는 경로를 설정합니다. 상대 경로를 지정합니다. 즉, http 또는 https 와 같이 지정하지 마십시오. camel-openapi-java modul은 이 형식의 런타임 시 절대 경로를 계산합니다: protocol://host:port/context-path/base.path.

CORS

부울

CORS(HTTP 액세스 제어) 활성화 여부입니다. 이렇게 하면 REST API 문서를 보는 경우에만 CORS를 활성화하고 REST 서비스에 액세스할 수 없습니다. 기본값은 false입니다. 이 테이블 뒤에 설명된 대로 CorsFilter 옵션을 대신 사용하는 것이 좋습니다.

host

문자열

OpenAPI 서비스가 실행 중인 호스트의 이름을 설정합니다. 기본값은 localhost 를 기반으로 호스트 이름을 계산하는 것입니다.

스키마

문자열

사용할 프로토콜 체계입니다. 쉼표로 여러 값을 구분합니다(예: "http,https"). 기본값은 http 입니다.

opeapi.version

문자열

OpenAPI 사양 버전. 기본값은 3.0입니다.

4.5.4. JSON 또는 YAML 출력 가져오기

Camel 3.1부터 camel-openapi-java 모듈은 JSON 및 YAML 형식의 출력을 모두 지원합니다. 원하는 출력을 지정하려면 /openapi.json 또는 /openapi.yaml 을 요청 URL에 추가합니다. 요청 URL이 형식을 지정하지 않으면 camel-openapi-java 모듈은 HTTP Accept 헤더를 검사하여 JSON 또는 YAML을 허용할 수 있는지 여부를 감지합니다. 둘 다 허용되거나 지원되는 것으로 설정되지 않은 경우 JSON은 기본 반환 형식입니다.

4.5.5. 예

Apache Camel 3.x 배포에서 camel-example-openapi-cdicamel-example- openapi-java 모듈을 사용하는 방법을 보여줍니다.

Apache Camel 2.x 배포판에서 camel-example-swagger-cdicamel-example-swagger-java 모듈은 camel-swagger-java 모듈을 사용하는 방법을 보여줍니다.

4.5.6. OpenAPI에서 생성된 문서 개선

Camel 3.1부터 이름, 설명, 데이터 유형, 매개변수 유형과 같은 매개변수 세부 정보를 정의하여 OpenAPI에서 생성한 문서를 개선할 수 있습니다. XML을 사용하는 경우 이 정보를 추가할 param 요소를 지정합니다. 다음 예제에서는 ID 경로 매개변수에 대한 정보를 제공하는 방법을 보여줍니다.

<!-- This is a REST GET request to view information for the user with the given ID: -->
<get uri="/{id}" outType="org.apache.camel.example.rest.User">
     <description>Find user by ID.</description>
     <param name="id" type="path" description="The ID of the user to get information about." dataType="int"/>
     <to uri="bean:userService?method=getUser(${header.id})"/>
</get>

다음은 Java DSL의 예는 다음과 같습니다.

.get("/{id}").description("Find user by ID.").outType(User.class)
   .param().name("id").type(path).description("The ID of the user to get information about.").dataType("int").endParam()
   .to("bean:userService?method=getUser(${header.id})")

이름이 본문인 매개변수를 정의하는 경우 body 를 해당 매개변수 유형으로 지정해야 합니다. 예를 들면 다음과 같습니다.

<!-- This is a REST PUT request to create/update information about a user. -->
<put type="org.apache.camel.example.rest.User">
     <description>Updates or creates a user.</description>
     <param name="body" type="body" description="The user to update or create."/>
     <to uri="bean:userService?method=updateUser"/>
</put>

다음은 Java DSL의 예는 다음과 같습니다.

.put().description("Updates or create a user").type(User.class)
     .param().name("body").type(body).description("The user to update or create.").endParam()
     .to("bean:userService?method=updateUser")

Apache Camel 배포에서 examples/camel-example-servlet-rest-tomcat 도 참조하십시오.

5장. 메시징 시스템

초록

이 장에서는 엔드포인트, 메시징 채널 및 메시지 라우터와 같은 메시징 시스템의 기본 구성 블록을 소개합니다.

5.1. 메시지

5.1.1. 개요

메시지는 메시징 시스템에서 데이터를 전송하기 위한 가장 작은 단위입니다(아래 그림의 회색 점으로 표시됨). 메시지 자체에는 몇 가지 내부 구조가 있을 수 있습니다. 예를 들어, 여러 parts Cryostat를 포함하는 메시지는 그림 5.1. “메시지 패턴” 의 회색 점에 연결된 기하학적 그림으로 표시됩니다.

그림 5.1. 메시지 패턴

메시지 패턴

5.1.2. 메시지 유형

Apache Camel은 다음과 같은 고유한 메시지 유형을 정의합니다.

  • 메시지 Cryostat- Cryostat 에서 소비자 끝점에서 생산자 엔드포인트(일반적으로 메시지 교환 시작)로 경로를 통과하는 메시지입니다.
  • 메시지 Cryostat- Cryostat는 생산자 끝점에서 소비자 끝점(일반적으로 In 메시지에 대한 응답으로)으로 경로를 통과하는 메시지입니다.

이러한 메시지 유형은 모두 org.apache.camel.Message 인터페이스로 내부적으로 표시됩니다.

5.1.3. 메시지 구조

기본적으로 Apache Camel은 모든 메시지 유형에 다음 구조를 적용합니다.

  • 메시지에서 추출된 메타데이터 또는 헤더 데이터를 포함합니다.Contains metadata or header data extracted from the message.
  • 본문 Cryostat - 일반적으로 원래 형식으로 전체 메시지를 포함합니다.
  • 첨부 파일 ( JBI와 같은 특정 메시징 시스템과 통합하기 위해 필수)

이 분할은 헤더, 본문 및 첨부 파일로 분할하는 것이 메시지의 추상 모델입니다. Apache Camel은 다양한 메시지 형식을 생성하는 다양한 구성 요소를 지원합니다. 궁극적으로 메시지 헤더 및 본문에 배치되는 항목을 결정하는 기본 구성 요소 구현입니다.

5.1.4. 메시지 연결

내부적으로 Apache Camel은 개별 메시지의 상관 관계를 유지하는 데 사용되는 메시지 ID를 기억합니다. 그러나 실제로 Apache Camel이 메시지의 상관 관계를 유지하는 가장 중요한 방법은 교환 오브젝트를 사용하는 것입니다.

5.1.5. 오브젝트 교환

교환 오브젝트는 관련 메시지를 캡슐화하는 엔티티로, 관련 메시지의 컬렉션을 메시지 교환 이라고 하며, 메시지 시퀀스를 관리하는 규칙을 교환 패턴 이라고 합니다. 예를 들어, 두 가지 일반적인 교환 패턴은 단방향 이벤트 메시지(메시지 포함) 및 요청 대응( In 메시지 포함) 및 외부 메시지입니다.

5.1.6. 메시지 액세스

Java DSL에서 라우팅 규칙을 정의할 때 다음과 같은 DSL 빌더 방법을 사용하여 메시지의 헤더 및 본문에 액세스할 수 있습니다.

  • header(String name), body() Cryostat- function은 named 헤더와 현재 In message의 본문을 반환합니다.
  • outBody() Cryostat- function 현재 Out 메시지의 본문을 반환합니다.

예를 들어 In 메시지의 사용자 이름 헤더를 채우려면 다음 Java DSL 경로를 사용할 수 있습니다.

from(SourceURL).setHeader("username", "John.Doe").to(TargetURL);

5.2. 메시지 채널

5.2.1. 개요

메시지 채널은 메시징 시스템의 논리 채널입니다. 즉, 다른 메시지 채널에 메시지를 보내는 것은 메시지를 다른 메시지 유형으로 정렬하는 기본 방법을 제공합니다. 메시지 대기열 및 메시지 주제는 메시지 채널의 예입니다. 논리 채널이 물리적 채널과 같지 않아야 합니다. 논리적 채널을 물리적으로 인식하는 여러 가지 방법이 있을 수 있습니다.

Apache Camel에서 메시지 채널은 그림 5.2. “메시지 채널 패턴” 에 표시된 대로 메시지 지향 구성 요소의 끝점 URI로 표시됩니다.

그림 5.2. 메시지 채널 패턴

메시지 채널 패턴

5.2.2. 메시지 지향 구성 요소

Apache Camel의 다음과 같은 메시지 지향 구성 요소는 메시지 채널의 개념을 지원합니다.

5.2.3. ActiveMQ

ActiveMQ에서 메시지 채널은 대기열 또는 주제로 표시됩니다. 특정 큐의 엔드포인트 URI인 QueueName 의 형식은 다음과 같습니다.

activemq:QueueName

특정 주제의 엔드포인트 URI인 TopicName 의 형식은 다음과 같습니다.

activemq:topic:TopicName

예를 들어 메시지를 큐에 보내려면 Foo.Bar 에서는 다음 끝점 URI를 사용합니다.

activemq:Foo.Bar

ActiveMQ 구성 요소 설정에 대한 자세한 내용 및 자세한 내용은 Apache Camel 구성 요소 참조 가이드 의 ActiveMQ를 참조하십시오.

5.2.4. JMS

JMS(Java Messaging Service)는 다양한 종류의 메시지 시스템에 액세스하는 데 사용되는 일반적인 래퍼 계층입니다(예: ActiveMQ, MQSeries, Tibco, BEA, Sonic 등). JMS에서 메시지 채널은 대기열 또는 주제로 표시됩니다. 특정 큐의 엔드포인트 URI인 QueueName 의 형식은 다음과 같습니다.

jms:QueueName

특정 주제의 엔드포인트 URI인 TopicName 의 형식은 다음과 같습니다.

jms:topic:TopicName

JMS 구성 요소 설정에 대한 자세한 내용 및 지침은 Apache Camel 구성 요소 참조 가이드Jms 를 참조하십시오.

5.2.5. AMQP

AMQP에서 메시지 채널은 대기열 또는 주제로 표시됩니다. 특정 큐의 엔드포인트 URI인 QueueName 의 형식은 다음과 같습니다.

amqp:QueueName

특정 주제의 엔드포인트 URI인 TopicName 의 형식은 다음과 같습니다.

amqp:topic:TopicName

AMQP 구성 요소 설정에 대한 자세한 내용 및 자세한 내용은 Apache Camel 구성 요소 참조 가이드Amqp 를 참조하십시오.

5.3. 메시지 끝점

5.3.1. 개요

메시지 끝점 은 애플리케이션과 메시징 시스템 간의 인터페이스입니다. 그림 5.3. “메시지 끝점 패턴” 에 표시된 대로 보낸 사람 끝점을 사용할 수 있습니다. 발신자 끝점은 메시지 전송을 담당하는 프록시 또는 서비스 소비자이며, 메시지 수신을 담당하는 끝점 또는 서비스 끝점이라고도 하는 수신자 끝점 있을 수 있습니다.

그림 5.3. 메시지 끝점 패턴

메시지 끝점 패턴

5.3.2. 끝점 유형

Apache Camel은 두 가지 기본 유형의 엔드포인트를 정의합니다.

  • 소비자 끝점 의 시작 부분에서 Apache Camel 경로가 표시되고 들어오는 채널( 수신 끝점과 동일)에서 In 메시지를 읽습니다.
  • 프로듀서 끝점 Cryostat-ition - Apache Camel 경로가 끝날 때 전달되고 발신 채널( 전송 끝점과 동일)에 In 메시지를 씁니다. 여러 생산자 엔드포인트가 있는 경로를 정의할 수 있습니다.

5.3.3. 엔드포인트 URI

Apache Camel에서 엔드포인트는 일반적으로 다음과 같은 종류의 데이터를 캡슐화하는 엔드포인트 URI 로 표시됩니다.

  • 소비자 끝점에 대한 엔드포인트 URI (예: 발신자가 연결할 수 있는 서비스를 노출하는 경우) 특정 위치 알림을 받습니다. 또는 URI에서 메시지 큐와 같은 메시지 소스를 지정할 수 있습니다. 엔드포인트 URI에는 엔드포인트를 구성하는 설정이 포함될 수 있습니다.
  • 생산자 엔드포인트에 대한 엔드포인트 URI Cryostat- Cryostat에는 메시지를 보낼 위치에 대한 세부 정보가 포함되어 있으며 엔드포인트를 구성하는 설정이 포함됩니다. 경우에 따라 URI는 원격 수신자 끝점의 위치를 지정합니다. 다른 경우 대상에는 대기열 이름과 같은 추상 형식이 있을 수 있습니다.

Apache Camel의 엔드포인트 URI에는 다음과 같은 일반적인 형식이 있습니다.

ComponentPrefix:ComponentSpecificURI

여기서 ComponentPrefix 는 특정 Apache Camel 구성 요소를 식별하는 URI 접두사입니다(지원되는 모든 구성 요소에 대한 자세한 내용은 Apache Camel 구성 요소 참조 참조 ). URI의 나머지 부분인 ComponentSpecificURI 에는 특정 구성 요소에서 정의한 구문이 있습니다. 예를 들어, Foo.Bar JMS 큐에 연결하려면 다음과 같이 엔드포인트 URI를 정의할 수 있습니다.

jms:Foo.Bar

소비자 끝점인 file://local/router/messages/foo 를 생산자 끝점에 직접 연결하는 경로를 정의하려면 jms:Foo.Bar 를 사용하여 다음 Java DSL 조각을 사용할 수 있습니다.

from("file://local/router/messages/foo").to("jms:Foo.Bar");

또는 다음과 같이 XML로 동일한 경로를 정의할 수 있습니다.

<camelContext id="CamelContextID" xmlns="http://camel.apache.org/schema/spring">
  <route>
    <from uri="file://local/router/messages/foo"/>
    <to uri="jms:Foo.Bar"/>
  </route>
</camelContext>

5.3.4. 동적 대상

& lt;toD > 매개변수를 사용하면 서로 연결된 하나 이상의 표현식을 사용하여 동적으로 계산된 엔드포인트에 메시지를 보낼 수 있습니다.

기본적으로 Simple 언어는 엔드포인트를 계산하는 데 사용됩니다. 다음 예제에서는 헤더에 의해 정의된 엔드포인트에 메시지를 보냅니다.

<route>
  <from uri="direct:start"/>
  <toD uri="${header.foo}"/>
</route>

Java DSL에서 동일한 명령의 형식은 다음과 같습니다.

from("direct:start")
  .toD("${header.foo}");

다음 예와 같이 URI 앞에 리터럴 접두사를 지정할 수도 있습니다.

<route>
  <from uri="direct:start"/>
  <toD uri="mock:${header.foo}"/>
</route>

Java DSL에서 동일한 명령의 형식은 다음과 같습니다.

from("direct:start")
  .toD("mock:${header.foo}");

위의 예에서 header.foo의 값이 주황색 인 경우 URI는 mock:orange 로 확인됩니다.

Simple 이외의 언어를 사용하려면 language: 매개변수를 정의해야 합니다. II 부. 라우팅 표현식 및 서술자 언어을 참조하십시오.

다른 언어를 사용하는 형식은 URI에서 language : language:language: 를 사용하는 것입니다. 예를 들어 Xpath를 사용하려면 다음 형식을 사용합니다.

<route>
  <from uri="direct:start"/>
  <toD uri="language:xpath:/order/@uri/">
</route>

다음은 Java DSL과 동일한 예입니다.

from("direct:start")
  .toD("language:xpath:/order/@uri");

language: 를 지정하지 않으면 끝점은 구성 요소 이름입니다. 경우에 따라 구성 요소와 언어의 이름이 xquery와 같은 경우가 있습니다.

+ 기호를 사용하여 여러 언어를 연결할 수 있습니다. 아래 예제에서 URI는 Simple 및 Xpath 언어의 조합입니다. Simple 가 기본값이므로 언어를 정의할 필요가 없습니다. + 기호가 Xpath 명령 후 언어:xpath 로 표시됩니다.

<route>
  <from uri="direct:start"/>
  <toD uri="jms:${header.base}+language:xpath:/order/@id"/>
</route>

Java DSL에서 형식은 다음과 같습니다.

from("direct:start")
  .toD("jms:${header.base}+language:xpath:/order/@id");

한 번에 많은 언어를 연결하고 각각 + 와 분리하고 언어 이름. language 로 각 언어를 지정할 수 있습니다.

다음 옵션을 toD 로 사용할 수 있습니다.

이름

기본값

설명

uri

 

필수: 사용할 URI입니다.

패턴

 

엔드포인트로 보낼 때 사용할 특정 교환 패턴을 설정합니다. 원래 MEP는 나중에 다시 설정됩니다.

cacheSize

 

재사용을 위해 생산자를 캐시하는 ProducerCache 의 캐시 크기를 구성합니다. 기본 캐시 크기는 1000이며 다른 값이 지정되지 않은 경우 사용됩니다. 값을 -1로 설정하면 캐시가 완전히 꺼집니다.

ignoreInvalidEndpoint

false

확인할 수 없는 엔드포인트 URI를 무시할지 여부를 지정합니다. 비활성화된 경우 Camel에서 잘못된 엔드포인트 URI를 식별하는 예외가 발생합니다.

5.4. 파이프 및 필터

5.4.1. 개요

그림 5.4. “파이프 및 필터 패턴” 에 표시된 파이프 및 필터 패턴은 필터 체인을 생성하여 경로를 구성하는 방법을 설명합니다. 여기서 하나의 필터 출력은 파이프라인의 다음 필터 입력에 제공됩니다(UNIX 파이프 명령과 분석). 파이프라인 접근 방식의 장점은 보다 복잡한 메시지 처리를 생성하기 위해 서비스( Apache Camel 애플리케이션 외부에 있을 수 있는 서비스)를 구성할 수 있다는 점입니다.

그림 5.4. 파이프 및 필터 패턴

파이프 및 필터 패턴

5.4.2. InOut 교환 패턴의 파이프라인

일반적으로 파이프라인의 모든 끝점에는 입력(in message) 및 출력(Out 메시지)이 있으며 이는 In Out 메시지 교환 패턴과 호환됨을 의미합니다. InOut 파이프라인을 통한 일반적인 메시지 흐름은 그림 5.5. “InOut Exchanges용 파이프라인” 에 표시됩니다.

그림 5.5. InOut Exchanges용 파이프라인

InOut 교환을 위한 파이프 라인

파이프라인은 각 끝점의 출력을 다음 끝점의 입력에 연결합니다. 최종 끝점의 아웃 메시지는 원래 호출자로 다시 전송됩니다. 다음과 같이 이 파이프라인의 경로를 정의할 수 있습니다.

from("jms:RawOrders").pipeline("cxf:bean:decrypt", "cxf:bean:authenticate", "cxf:bean:dedup", "jms:CleanOrders");

다음과 같이 XML로 동일한 경로를 구성할 수 있습니다.

<camelContext id="buildPipeline" xmlns="http://camel.apache.org/schema/spring">
  <route>
    <from uri="jms:RawOrders"/>
    <to uri="cxf:bean:decrypt"/>
    <to uri="cxf:bean:authenticate"/>
    <to uri="cxf:bean:dedup"/>
    <to uri="jms:CleanOrders"/>
  </route>
</camelContext>

XML에는 전용 파이프라인 요소가 없습니다. 앞에 있는 요소와 요소 간의 결합은 파이프라인과 의미적으로 동일합니다. “pipeline() 및 to() DSL 명령 비교”을 참조하십시오.

5.4.3. InOnly 및 RobustInOnly 교환 패턴의 파이프라인

파이프라인의 끝점에서 사용 가능한 Out 메시지( InOnlyRobustInOnly 교환 패턴의 경우)가 없는 경우 파이프라인을 일반적인 방식으로 연결할 수 없습니다. 이 특별한 경우 그림 5.6. “InOnly 교환을 위한 파이프라인” 에 표시된 것처럼 파이프라인은 원래 In 메시지 사본을 파이프라인의 각 끝점에 전달하여 구성됩니다. 이 유형의 파이프라인은 고정 대상이 있는 수신자 목록과 동일합니다( 8.3절. “수신자 목록”참조).

그림 5.6. InOnly 교환을 위한 파이프라인

InOnly 교환을 위한 파이프 라인

이 파이프라인의 경로는 InOut 파이프라인(Java DSL 또는 XML)과 동일한 구문을 사용하여 정의됩니다.

5.4.4. pipeline() 및 to() DSL 명령 비교

Java DSL에서는 다음 구문 중 하나를 사용하여 파이프라인 경로를 정의할 수 있습니다.

  • pipeline() 프로세서 명령 Cryo stat- Cryostat를 사용하여 파이프라인 프로세서를 사용하여 다음과 같이 파이프라인 경로를 구성합니다.

    from(SourceURI).pipeline(FilterA, FilterB, TargetURI);
  • to() 명령을 사용하여 다음과 같이 to() 명령을 사용하여 파이프라인 경로를 구성합니다.

    from(SourceURI).to(FilterA, FilterB, TargetURI);

    또는 동등한 구문을 사용할 수 있습니다.

    from(SourceURI).to(FilterA).to(FilterB).to(TargetURI);

파이프라인 프로세서와 항상 동일하지 않기 때문에 to() 명령 구문을 사용할 때는 주의하십시오. Java DSL에서 to() 의 의미는 경로의 이전 명령으로 수정할 수 있습니다. 예를 들어 multicast() 명령이 to() 명령 앞에 있을 때 파이프라인 패턴 대신 나열된 끝점을 멀티 캐스트 패턴에 바인딩합니다( 8.13절. “멀티 캐스트”참조).

5.5. 메시지 라우터

5.5.1. 개요

그림 5.7. “메시지 라우터 패턴” 에 표시된 메시지 라우터 는 단일 소비자 끝점의 메시지를 사용하고 특정 의사 결정 기준에 따라 적절한 대상 끝점으로 리디렉션하는 필터 유형입니다. 메시지 라우터는 메시지를 리디렉션하는 데만 관련이 있습니다. 메시지 내용은 수정되지 않습니다.

그러나 기본적으로 Camel이 메시지 교환을 수신자 엔드포인트로 라우팅할 때마다 원본 교환 오브젝트의 단순 복사본입니다. 부분 복사에서는 메시지 본문, 헤더 및 첨부 파일과 같은 원래 교환의 요소는 참조용으로만 복사됩니다. Camel은 리소스를 재사용하는 단순 복사본을 전송하여 성능을 위해 최적화합니다. 그러나 이러한 부분 사본이 모두 연결되어 있기 때문에 Camel이 메시지를 여러 끝점으로 라우팅하는 경우 장단점은 다른 수신자로 라우팅되는 사본에 사용자 정의 논리를 적용할 수 있다는 것입니다. Camel에서 고유한 버전의 메시지를 다른 엔드포인트로 라우팅하는 방법에 대한 자세한 내용은 "계속 메시지에 사용자 정의 처리"를 참조하십시오.

그림 5.7. 메시지 라우터 패턴

메시지 라우터 패턴

메시지 라우터는 choose () 프로세서를 사용하여 Apache Camel에서 쉽게 구현할 수 있습니다. 여기서 각 대체 대상 끝점은 when() 하위 옵션을 사용하여 선택할 수 있습니다(선택 프로세서에 대한 자세한 내용은 1.5절. “프로세서”참조).

5.5.2. Java DSL 예

다음 Java DSL 예제에서는 foo 헤더의 콘텐츠에 따라 세 가지 대체 대상( seda:a,seda:b 또는 seda:c)으로 메시지를 라우팅하는 방법을 보여줍니다.

from("seda:a").choice()
    .when(header("foo").isEqualTo("bar")).to("seda:b")
    .when(header("foo").isEqualTo("cheese")).to("seda:c")
    .otherwise().to("seda:d");

5.5.3. XML 구성 예

다음 예제에서는 XML로 동일한 경로를 구성하는 방법을 보여줍니다.

<camelContext id="buildSimpleRouteWithChoice" xmlns="http://camel.apache.org/schema/spring">
  <route>
    <from uri="seda:a"/>
    <choice>
      <when>
        <xpath>$foo = 'bar'</xpath>
        <to uri="seda:b"/>
      </when>
      <when>
        <xpath>$foo = 'cheese'</xpath>
        <to uri="seda:c"/>
      </when>
      <otherwise>
        <to uri="seda:d"/>
      </otherwise>
    </choice>
  </route>
</camelContext>

5.5.4. 그렇지 않은 경우 선택

otherwise() 절 없이 choice() 을 사용하면 일치하지 않는 교환이 기본적으로 삭제됩니다.

5.6. 메시지#159

5.6.1. 개요

그림 5.8. “메시지#159 패턴” 에 표시된 메시지 번역 패턴은 메시지의 내용을 수정하여 다른 형식으로 변환하는 구성 요소를 설명합니다. Apache Camel의 8080 통합 기능을 사용하여 메시지 변환을 수행할 수 있습니다.

그림 5.8. 메시지#159 패턴

메시지 번역 패턴

5.6.2. Cryostat 통합

metrics 통합을 사용하여 메시지를 변환하여 등록된 모든 Cryostat에서 메서드를 호출할 수 있습니다. 예를 들어, myMethodName() 메서드를 호출하려면 빈에서 ID를 사용하여 myTransformerBean:

from("activemq:SomeQueue")
  .beanRef("myTransformerBean", "myMethodName")
  .to("mqseries:AnotherQueue");

여기서 myTransformerBean VLAN은 Spring XML 파일 또는 JNDI에 정의되어 있습니다. 8080 Ref() 에서 method name 매개변수를 생략하면, 8080 통합은 메시지 교환을 검사하여 메서드 이름을 추론하려고 합니다.

다음과 같이 자체 명시적 Processor 인스턴스를 추가하여 변환을 수행할 수도 있습니다.

from("direct:start").process(new Processor() {
    public void process(Exchange exchange) {
        Message in = exchange.getIn();
        in.setBody(in.getBody(String.class) + " World!");
    }
}).to("mock:result");

또는 DSL을 사용하여 다음과 같이 변환을 명시적으로 구성할 수 있습니다.

from("direct:start").setBody(body().append(" World!")).to("mock:result");

템플릿 작성을 사용하여 대상의 메시지를 사용하여 Velocity 또는 XQuery와 같은 것으로 변환한 다음 다른 대상으로 보낼 수도 있습니다. 예를 들어 InOnly 교환 패턴 (one-way 메시징) 사용 :

from("activemq:My.Queue").
  to("velocity:com/acme/MyResponse.vm").
  to("activemq:Another.Queue");

템플릿이 생성된 응답과 함께 ActiveMQ의 My.Queue 큐에서 요청을 처리하는 데 InOut (request-reply) 의미 체계를 사용하려면 다음과 같은 경로를 사용하여 JMSReplyTo 대상에 응답을 다시 보낼 수 있습니다.

from("activemq:My.Queue").
  to("velocity:com/acme/MyResponse.vm");

5.7. 메시지 내역

5.7.1. 개요

메시지 기록 패턴을 사용하면 느슨하게 연결된 시스템에서 메시지 흐름을 분석하고 디버깅할 수 있습니다. 메시지 기록을 메시지에 연결하면 메시지가 원본 이후 전달된 모든 애플리케이션 목록이 표시됩니다.

Apache Camel에서는 getTracedRouteNodes 방법을 사용하여 추적기를 사용하거나 UnitOfWork의 Java API를 사용하여 메시지 흐름을 추적할 수 있습니다.

5.7.2. 로그의 문자 길이 제한

로깅 메커니즘을 사용하여 Apache Camel을 실행하면 메시지 및 해당 콘텐츠를 수시로 기록할 수 있습니다.

일부 메시지에는 매우 큰 페이로드가 포함될 수 있습니다. 기본적으로 Apache Camel은 로그 메시지를 지우고 처음 1000자만 표시합니다. 예를 들어 다음 로그가 다음과 같이 표시됩니다.

[DEBUG ProducerCache  - >>>> Endpoint[direct:start] Exchange[Message: 01234567890123456789... [Body clipped after 20 characters, total length is 1000]

Apache Camel이 로그의 본문을 클리핑할 때 제한을 사용자 지정할 수 있습니다. 0 또는 음수 값(예: -1)을 설정할 수도 있습니다. 즉 메시지 본문이 기록되지 않음을 의미합니다.

Java DSL을 사용하여 제한 사용자 정의

Java DSL을 사용하여 Camel 속성의 제한을 설정할 수 있습니다. 예를 들면 다음과 같습니다.

 context.getProperties().put(Exchange.LOG_DEBUG_BODY_MAX_CHARS, "500");
Spring DSL을 사용하여 제한 사용자 정의

Spring DSL을 사용하여 Camel 속성 제한을 설정할 수 있습니다. 예를 들면 다음과 같습니다.

<camelContext>
    <properties>
        <property key="CamelLogDebugBodyMaxChars" value="500"/>
   </properties>
</camelContext>

6장. 메시징 채널

초록

메시징 채널에서는 메시징 애플리케이션의 배관을 제공합니다. 이 장에서는 메시징 시스템에서 사용할 수 있는 다양한 종류의 메시징 채널과 수행하는 역할에 대해 설명합니다.

6.1. point-to-Point 채널

6.1.1. 개요

그림 6.1. “채널 패턴 지정” 에 표시된 지점 간 채널은 하나의 수신자만 지정된 메시지를 사용하도록 보장하는 메시지 채널입니다. 이는 여러 수신자가 동일한 메시지를 사용할 수 있는 게시-서브스크립션 채널 과 대조됩니다. 특히 게시-서브스크립션 채널을 사용하면 여러 수신자가 동일한 채널에 서브스크립션할 수 있습니다. 둘 이상의 수신자가 메시지를 사용하기 위해 경쟁하는 경우 하나의 수신자만 메시지를 실제로 사용하도록 하는 메시지 채널에 달려 있습니다.

그림 6.1. 채널 패턴 지정

채널 패턴을 가리키기

6.1.2. 점대점 채널을 지원하는 구성 요소

다음 Apache Camel 구성 요소는 지점 간 채널 패턴을 지원합니다.

6.1.3. JMS

JMS에서 점대점 채널은 로 표시됩니다. 예를 들어 다음과 같이 Foo.Bar 라는 JMS 큐에 대한 엔드포인트 URI를 지정할 수 있습니다.

jms:queue:Foo.Bar

JMS 구성 요소가 기본적으로 큐 엔드포인트를 생성하므로 한정자인 queue: 는 선택 사항입니다. 따라서 다음과 동등한 끝점 URI를 지정할 수도 있습니다.

jms:Foo.Bar

자세한 내용은 Apache Camel 구성 요소 참조 가이드Jms 를 참조하십시오.

6.1.4. ActiveMQ

ActiveMQ에서 점대점 채널은 큐로 표시됩니다. 예를 들어 다음과 같이 Foo.Bar 라는 ActiveMQ 큐에 대한 엔드포인트 URI를 지정할 수 있습니다.

activemq:queue:Foo.Bar

자세한 내용은 Apache Camel 구성 요소 참조 가이드ActiveMQ 를 참조하십시오.

6.1.5. SEDA

Apache Camel Staged Event-Driven Architecture(SEDA) 구성 요소는 차단 대기열을 사용하여 구현됩니다. Apache Camel 애플리케이션 내부에 있는 경량 지점 간 채널을 생성하려면 SEDA 구성 요소를 사용합니다. 예를 들어 다음과 같이 SedaQueue 라는 SEDA 큐에 대한 엔드포인트 URI를 지정할 수 있습니다.

seda:SedaQueue

6.1.6. JPA

JPA(Java Persistence API) 구성 요소는 데이터베이스에 엔터티 빈을 작성하는 데 사용되는 handler 3 지속성 표준입니다. 자세한 내용은 Apache Camel 구성 요소 참조 가이드JPA 를 참조하십시오.

6.1.7. XMPP

XMPP(Jabber) 구성 요소는 직접 통신 모드에서 사용할 때 점대점 채널 패턴을 지원합니다. 자세한 내용은 Apache Camel 구성 요소 참조 가이드XMPP 를 참조하십시오.

6.2. 게시-서브스크립션 채널

6.2.1. 개요

그림 6.2. “서브스크립션 채널 패턴 게시” 에 표시된 게시-서브스크립션 채널은 여러 구독자가 지정된 메시지를 사용할 수 있는 5.2절. “메시지 채널” 입니다. 이는 6.1절. “point-to-Point 채널” 과 다릅니다. 게시-서브스크립션 채널은 여러 구독자에게 이벤트 또는 알림을 브로드캐스트하는 수단으로 자주 사용됩니다.

그림 6.2. 서브스크립션 채널 패턴 게시

서브스크립션 채널 패턴 게시

6.2.2. 게시-서브스크립션 채널을 지원하는 구성 요소

다음 Apache Camel 구성 요소는 publish-subscribe 채널 패턴을 지원합니다.

  • JMS
  • ActiveMQ
  • XMPP
  • SEDA 는 pub-sub에서 작동할 수 있지만 여러 소비자를 허용하는 동일한 CamelContext에서 SEDA로 작업하는 데 사용됩니다.
  • 동일한 JVM 내에서 사용할 수 있도록 Apache Camel 구성 요소 참조 가이드의 VM 을 SEDA로 참조하십시오.

6.2.3. JMS

JMS에서 게시-서브스크립션 채널은 주제로 표시됩니다. 예를 들어 다음과 같이 Cryostat Quotes라는 JMS 항목에 대한 엔드포인트 URI를 지정할 수 있습니다.

jms:topic:StockQuotes

자세한 내용은 Apache Camel 구성 요소 참조 가이드Jms 를 참조하십시오.

6.2.4. ActiveMQ

ActiveMQ에서 게시-서브스크립션 채널은 주제로 표시됩니다. 예를 들어 다음과 같이 Cryostat Quotes 라는 ActiveMQ 항목에 대한 엔드포인트 URI를 지정할 수 있습니다.

activemq:topic:StockQuotes

자세한 내용은 Apache Camel 구성 요소 참조 가이드ActiveMQ 를 참조하십시오.

6.2.5. XMPP

XMPP(Jabber) 구성 요소는 그룹 통신 모드에서 사용할 때 게시-서브스크립션 채널 패턴을 지원합니다. 자세한 내용은 Apache Camel 구성 요소 참조 가이드Xmpp 를 참조하십시오.

6.2.6. 정적 서브스크립션 목록

원하는 경우 Apache Camel 애플리케이션 자체 내에서 게시-서브스크립션 논리를 구현할 수도 있습니다. 간단한 접근 방식은 경로 끝에 대상 끝점이 모두 명시적으로 나열된 정적 서브스크립션 목록을 정의하는 것입니다. 그러나 이 접근 방식은 JMS 또는 ActiveMQ 주제만큼 유연하지 않습니다.

6.2.7. Java DSL 예

다음 Java DSL 예제에서는 단일 게시자, seda:a 및 세 구독자, seda:b:c, seda:d 를 사용하여 게시 구독 채널을 시뮬레이션하는 방법을 보여줍니다.

from("seda:a").to("seda:b", "seda:c", "seda:d");
참고

이는 InOnly 메시지 교환 패턴에서만 작동합니다.

6.2.8. XML 구성 예

다음 예제에서는 XML로 동일한 경로를 구성하는 방법을 보여줍니다.

<camelContext id="buildStaticRecipientList" xmlns="http://camel.apache.org/schema/spring">
  <route>
    <from uri="seda:a"/>
    <to uri="seda:b"/>
    <to uri="seda:c"/>
    <to uri="seda:d"/>
  </route>
</camelContext>

6.3. dead Letter Channel

6.3.1. 개요

그림 6.3. “dead letter 채널 패턴” 에 표시된 dead letter 채널 패턴은 메시징 시스템이 의도한 수신자에 메시지를 전달하지 못하는 경우 수행할 작업을 설명합니다. 여기에는 전달 재시도와 같은 기능이 포함되며, 전달이 궁극적으로 실패하는 경우 전달되지 않은 메시지를 보관하는 dead letter 채널로 메시지를 보냅니다.

그림 6.3. dead letter 채널 패턴

dead letter channel pattern

6.3.2. Java DSL에서 dead letter 채널 생성

다음 예제에서는 Java DSL을 사용하여 dead letter 채널을 생성하는 방법을 보여줍니다.

errorHandler(deadLetterChannel("seda:errors"));
from("seda:a").to("seda:b");

errorHandler() 메서드는 Java DSL 인터셉터이며, 이는 현재 경로 빌더에 정의된 모든 경로가 이 설정의 영향을 받는 것을 의미합니다. deadLetterChannel() 메서드는 지정된 대상 끝점인 seda:errors 를 사용하여 새 dead letter 채널을 생성하는 Java DSL 명령입니다.

errorHandler() 인터셉터는 모든 오류 유형을 처리하기 위한 catch- all 메커니즘을 제공합니다. 예외 처리에 보다 세분화된 접근 방식을 적용하려면 onException 절을 대신 사용할 수 있습니다( “onException 절”참조).

6.3.3. XML DSL 예

다음과 같이 XML DSL에서 dead letter 채널을 정의할 수 있습니다.

 <route errorHandlerRef="myDeadLetterErrorHandler">
    ...
 </route>

 <bean id="myDeadLetterErrorHandler" class="org.apache.camel.builder.DeadLetterChannelBuilder">
     <property name="deadLetterUri" value="jms:queue:dead"/>
     <property name="redeliveryPolicy" ref="myRedeliveryPolicyConfig"/>
 </bean>

 <bean id="myRedeliveryPolicyConfig" class="org.apache.camel.processor.RedeliveryPolicy">
     <property name="maximumRedeliveries" value="3"/>
     <property name="redeliveryDelay" value="5000"/>
 </bean>

6.3.4. Redelivery policy

일반적으로 전달 시도가 실패하는 경우 dead letter 채널에 직접 메시지를 보내지 않습니다. 대신 최대 제한까지 전송을 다시 시도하면 모든 재전송 시도가 실패하면 메시지를 dead letter 채널로 보냅니다. 메시지 재전송을 사용자 정의하기 위해 dead letter 채널을 구성하여 재전송 정책을 설정할 수 있습니다. 예를 들어 최대 두 개의 재전송 시도를 지정하고 지수 백오프 알고리즘을 전달 시도 사이의 시간 지연에 적용하려면 다음과 같이 dead letter 채널을 구성할 수 있습니다.

errorHandler(deadLetterChannel("seda:errors").maximumRedeliveries(2).useExponentialBackOff());
from("seda:a").to("seda:b");

체인에서 관련 메서드를 호출하여 dead letter 채널에 redelivery 옵션을 설정하는 경우 체인의 각 메서드는 현재 RedeliveryPolicy 오브젝트에 대한 참조를 반환합니다. 표 6.1. “Redelivery Policy Settings” 재전송 정책을 설정하는 데 사용할 수 있는 방법이 요약되어 있습니다.

표 6.1. Redelivery Policy Settings

메서드 서명Default설명

allowRedeliveryWhileStopping()

true

정상 종료 중에 또는 경로가 중지되는 동안 재전송이 시도되는지 여부를 제어합니다. 중지가 시작될 때 이미 진행 중인 제공은 중단 되지 않습니다.

backOffMultiplier(double multiplier)

2

exponential 백오프가 활성화된 경우 m 을 백오프 multiplier로 설정하고 d 를 초기 지연으로 설정합니다. 그런 다음 재전송 시도 시퀀스가 다음과 같이 시간 초과됩니다.

d, m*d, m*m*d, m*m*m*d, ...

collisionAvoidancePercent(double collisionAvoidancePercent)

15

충돌 방지 기능이 활성화된 경우 p 를 충돌 방지 백분율로 설정합니다. 그런 다음 충돌 방지 정책은 다음 지연을 현재 값의 plus/minus p% 까지 임의의 양만큼 조정합니다.

deadLetterHandleNewException

true

Camel 2.15: dead letter 채널에서 메시지를 처리하는 동안 발생하는 예외를 처리할지 여부를 지정합니다. true 인 경우 예외가 처리되고 WARN 수준에서 로깅되어 dead letter 채널이 완료되도록 합니다. false 인 경우 예외가 처리되지 않으므로 dead letter 채널이 실패하고 새 예외를 전파합니다.

delayPattern(String delayPattern)

없음

Apache Camel 2.0: “지연 패턴 재전송” 참조.

disableRedelivery()

true

Apache Camel 2.0: 재전송 기능을 비활성화합니다. 재전송을 활성화하려면 maximumRedeliveries() 를 양의 정수 값으로 설정합니다.

처리(부울 처리)

true

Apache Camel 2.0: true 인 경우 메시지가 dead letter 채널로 이동될 때 현재 예외가 지워집니다. false 인 경우 예외가 클라이언트에 다시 전파됩니다.

initialRedeliveryDelay(long initialRedeliveryDelay)

1000

첫 번째 재전송을 시도하기 전에 지연 (밀리초)을 지정합니다.

logNewException

true

dead letter 채널에서 예외가 발생하는 경우 WARN 수준에서 로그할지 여부를 지정합니다.

logStackTrace(boolean logStackTrace)

false

Apache Camel 2.0: true 인 경우 JVM 스택 추적이 오류 로그에 포함됩니다.

maximumRedeliveries(int maximumRedeliveries)

0

Apache Camel 2.0: 제공 시도의 최대 수입니다.

maximumRedeliveryDelay(long maxDelay)

60000

Apache Camel 2.0: 지수 백오프 전략을 사용하는 경우( ExponentialBackOff()참조)는 이론적으로 제한 없이 재전송 지연을 늘릴 수 있습니다. 이 속성은 재전송 지연(밀리초)에 상한 제한을 적용합니다.

onRedelivery(프로세서 프로세서)

없음

Apache Camel 2.0: 모든 재전송 시도 전에 호출되는 프로세서를 구성합니다.

redeliveryDelay(long int)

0

Apache Camel 2.0: 재전송 시도 사이의 지연(밀리초)을 지정합니다. Apache Camel 2.16.0: 기본 재전송 지연은 1초입니다.

retriesExhaustedLogLevel(LoggingLevel logLevel)

LoggingLevel.ERROR

Apache Camel 2.0: 전송 실패를 기록할 로깅 수준을 지정합니다( org.apache.camel.LoggingLevel 상수로 지정됨).

retryAttemptedLogLevel(LoggingLevel logLevel)

LoggingLevel.DEBUG

Apache Camel 2.0: 시도를 다시 전달할 로깅 수준을 지정합니다( org.apache.camel.LoggingLevel 상수로 지정됨).

useCollisionAvoidance()

false

경합 가능성을 줄이기 위해 백오프 타이밍에 일부 임의화를 추가하는 충돌 방지를 활성화합니다.

useOriginalMessage()

false

Apache Camel 2.0: 이 기능이 활성화되면 dead letter 채널로 전송된 메시지는 경로 시작 부분에 존재하기 때문에 원래 메시지 교환의 사본입니다( from() 노드).

useExponentialBackOff()

false

지수 백오프를 활성화합니다.

6.3.5. 헤더 재전송

Apache Camel이 메시지를 다시 전달하려고 하면 In 메시지의 표 6.2. “dead letter Redelivery Headers” 에 설명된 헤더가 자동으로 설정됩니다.

표 6.2. dead letter Redelivery Headers

헤더 이름유형설명

CamelRedeliveryCounter

정수

Apache Camel 2.0: 실패한 제공 시도 횟수를 계산합니다. 이 값은 Exchange.REDELIVERY_COUNTER 에서도 설정됩니다.

CamelRedelivered

부울

Apache Camel 2.0: 하나 이상의 재전송 시도가 이루어진 경우 True입니다. 이 값은 Exchange.REDELIVERED 에서도 설정됩니다.

CamelRedeliveryMaxCounter

정수

Apache Camel 2.6: 최대 재전송 설정을 유지합니다( Exchange.REDELIVERY_MAX_COUNTER 교환 속성에 설정됨). retryWhile 를 사용하거나 무제한 최대 재전송이 구성된 경우 이 헤더가 없습니다.

6.3.6. Redelivery exchange properties

Apache Camel이 메시지를 다시 전달하려고 하면 표 6.3. “교환 속성 재전송” 에 설명된 교환 속성이 자동으로 설정됩니다.

표 6.3. 교환 속성 재전송

자산 이름 교환유형설명

Exchange.FAILURE_ROUTE_ID

문자열

실패한 경로의 경로 ID를 제공합니다. 이 속성의 리터럴 이름은 CamelFailureRouteId 입니다.

6.3.7. 원본 메시지 사용

Apache Camel 2.0부터 사용할 수 있습니다. 교환 오브젝트는 경로를 통해 전달될 때 수정될 수 있으므로 예외가 발생한 경우 현재 교환이 dead letter 채널에 저장하려는 사본이 아닙니다. 대부분의 경우 경로에서 모든 종류의 변환이 적용되기 전에 경로 시작 부분에 도착한 메시지를 기록하는 것이 좋습니다. 예를 들어 다음 경로를 고려하십시오.

from("jms:queue:order:input")
       .to("bean:validateOrder");
       .to("bean:transformOrder")
       .to("bean:handleOrder");

이전 경로는 들어오는 JMS 메시지를 수신 대기한 다음, beans 시퀀스를 사용하여 메시지를 처리합니다. validateOrder,transformOrder, handleOrder. 그러나 오류가 발생하면 메시지가 어떤 상태에 있는지 알 수 없습니다. transformOrder Cryostat 또는 이후 버전 이전에 오류가 발생했습니까? 다음과 같이 original message from jms:queue:order:input 가 dead letter channel에 기록되도록 수 있습니다.

// will use original body
errorHandler(deadLetterChannel("jms:queue:dead")
       .useOriginalMessage().maximumRedeliveries(5).redeliveryDelay(5000);

6.3.8. 지연 패턴 재전송

Apache Camel 2.0에서 사용 가능한 delay 옵션은 redelivery count의 특정 범위에 대한 지연을 지정하는 데 사용됩니다. 지연 패턴에는 다음과 같은 구문이 있습니다. limit1:delay1;limit2:delay2;limit3:delay3 ;…​ ...여기서 각 delayN 은 범위limitN cidr redeliveryCount < limitN+1 의 재전송에 적용됩니다.

예를 들어 다음 재전송 지연에 세 개의 그룹을 정의하는 5:1000;10:5000;20:20000 패턴을 고려해 보십시오.

  • 1..4 = 0밀리초(첫 번째 그룹이 5로 시작됨)를 시도합니다.
  • 5..9 = 1000밀리초(첫 번째 그룹)를 시도합니다.
  • 10..19 = 5000밀리초(두 번째 그룹)를 시도합니다.
  • 20.. = 20000밀리초(마지막 그룹)를 시도합니다.

limit 1로 그룹을 시작하여 시작 지연을 정의할 수 있습니다. 예를 들어 1:1000;5:5000 으로 인해 다음과 같은 재전송 지연이 발생합니다.

  • 1..4 = 1000 밀리 밀리 (첫 번째 그룹)
  • 시도 번호 5.. = 5000 밀리 밀리 (마지막 그룹)

다음 지연이 이전보다 커야 한다는 요구 사항은 없으며 원하는 지연 값을 사용할 수 있습니다. 예를 들어 지연 패턴 1:5000;3:1000 은 5초 지연으로 시작하고 지연을 1초로 줄입니다.

6.3.9. 어떤 엔드 포인트가 실패합니까?

Apache Camel이 메시지를 라우팅하면 교환이 전송된 마지막 끝점이 포함된 Exchange 속성을 업데이트합니다. 따라서 다음 코드를 사용하여 현재 교환의 최신 대상에 대한 URI를 얻을 수 있습니다.

// Java
String lastEndpointUri = exchange.getProperty(Exchange.TO_ENDPOINT, String.class);

여기서 Exchange.TO_ENDPOINTCamelToEndpoint 와 동일한 문자열 상수입니다. 이 속성은 Camel이 모든 엔드포인트에 메시지를 전송할 때마다 업데이트됩니다.

라우팅 중에 오류가 발생하고 교환이 dead letter queue로 이동되는 경우 Apache Camel은 오류가 발생하기 전에 교환이 전송된 마지막 대상을 식별하는 CamelFailureEndpoint 라는 속성을 추가로 설정합니다. 따라서 다음 코드를 사용하여 dead letter 큐 내에서 실패 끝점에 액세스할 수 있습니다.

// Java
String failedEndpointUri = exchange.getProperty(Exchange.FAILURE_ENDPOINT, String.class);

여기서 Exchange.FAILURE_ENDPOINTCamelFailureEndpoint 와 동일한 문자열 상수입니다.

참고

이러한 속성은 지정된 대상 끝점 처리가 완료된 후에도 오류가 발생하더라도 현재 교환에 설정된 상태로 유지됩니다. 예를 들어 다음 경로를 고려하십시오.

        from("activemq:queue:foo")
        .to("http://someserver/somepath")
        .beanRef("foo");

이제 foo 8080에서 오류가 발생한다고 가정합니다. 이 경우 Exchange.TO_ENDPOINT 속성 및 Exchange.FAILURE_ENDPOINT 속성에는 값이 계속 포함됩니다.

6.3.10. OnRedelivery 프로세서

dead letter 채널이 redeliveries를 수행할 때 모든 재전송 시도 바로 전에 실행되는 Processor 를 구성할 수 있습니다. 이는 메시지를 재전송하기 전에 변경해야 하는 경우에 사용할 수 있습니다.

예를 들어 다음 dead letter 채널은 교환을 재전송하기 전에 MyRedeliverProcessor 를 호출하도록 구성되어 있습니다.

// we configure our Dead Letter Channel to invoke
// MyRedeliveryProcessor before a redelivery is
// attempted. This allows us to alter the message before
errorHandler(deadLetterChannel("mock:error").maximumRedeliveries(5)
        .onRedelivery(new MyRedeliverProcessor())
        // setting delay to zero is just to make unit teting faster
        .redeliveryDelay(0L));

MyRedeliveryProcessor 프로세스가 다음과 같이 구현되는 경우:

// This is our processor that is executed before every redelivery attempt
// here we can do what we want in the java code, such as altering the message
public class MyRedeliverProcessor implements Processor {

    public void process(Exchange exchange) throws Exception {
        // the message is being redelivered so we can alter it

        // we just append the redelivery counter to the body
        // you can of course do all kind of stuff instead
        String body = exchange.getIn().getBody(String.class);
        int count = exchange.getIn().getHeader(Exchange.REDELIVERY_COUNTER, Integer.class);

        exchange.getIn().setBody(body + count);

        // the maximum redelivery was set to 5
        int max = exchange.getIn().getHeader(Exchange.REDELIVERY_MAX_COUNTER, Integer.class);
        assertEquals(5, max);
    }
}

6.3.11. 종료 또는 중지 중 재전송 제어

경로를 중지하거나 정상 종료를 시작하는 경우 오류 처리기의 기본 동작은 재전송을 계속 시도하는 것입니다. 일반적으로 원하는 동작이 아니므로 다음 예와 같이 allowRedeliveryWhileStopping 옵션을 false 로 설정하여 종료 또는 중지 중에 재전송을 비활성화할 수 있습니다.

errorHandler(deadLetterChannel("jms:queue:dead")
    .allowRedeliveryWhileStopping(false)
    .maximumRedeliveries(20)
    .redeliveryDelay(1000)
    .retryAttemptedLogLevel(LoggingLevel.INFO));
참고

이전 버전과의 호환성을 위해 allowRedeliveryWhileStopping 옵션은 기본적으로 적용됩니다. 그러나 공격적인 종료 중에 이 옵션 설정에 관계없이 재전송이 항상 억제됩니다(예: 정상 종료 후 시간 초과).

6.3.12. onExceptionOccurred Processor 사용

dead Letter 채널은 예외가 발생한 후 메시지의 사용자 지정 처리를 허용하도록 onExceptionOccurred 프로세서를 지원합니다. 사용자 지정 로깅에도 사용할 수 있습니다. onExceptionOccurred 프로세서에서 발생한 새로운 예외는 WARN으로 기록되고 기존 예외를 재정의하지 않도록 무시합니다.

onRedelivery 프로세서와 onExceptionOccurred 프로세서의 차이점은 재전송 시도 직전에 이전을 처리할 수 있다는 것입니다. 그러나 예외가 발생한 직후에 발생하지 않습니다. 예를 들어 재전송 시도 사이에 5초 지연을 수행하도록 오류 처리기를 구성하는 경우 예외가 발생한 후 5초 후에 재전송 프로세서가 호출됩니다.

다음 예제에서는 예외가 발생할 때 사용자 지정 로깅을 수행하는 방법을 설명합니다. 사용자 지정 프로세서를 사용하려면 onExceptionOccurred를 구성해야 합니다.

errorHandler(defaultErrorHandler().maximumRedeliveries(3).redeliveryDelay(5000).onExceptionOccurred(myProcessor));

6.3.13. onException 절

경로 빌더에서 errorHandler() 인터셉터를 사용하는 대신 다양한 예외 유형에 대해 다양한 재전송 정책 및 다양한 dead letter 채널을 정의하는 일련의 onException() 절을 정의할 수 있습니다. 예를 들어 각 NullPointerException,IOExceptionException 유형에 대해 고유한 동작을 정의하려면 Java DSL을 사용하여 경로 빌더에서 다음 규칙을 정의할 수 있습니다.

onException(NullPointerException.class)
    .maximumRedeliveries(1)
    .setHeader("messageInfo", "Oh dear! An NPE.")
    .to("mock:npe_error");

onException(IOException.class)
    .initialRedeliveryDelay(5000L)
    .maximumRedeliveries(3)
    .backOffMultiplier(1.0)
    .useExponentialBackOff()
    .setHeader("messageInfo", "Oh dear! Some kind of I/O exception.")
    .to("mock:io_error");

onException(Exception.class)
    .initialRedeliveryDelay(1000L)
    .maximumRedeliveries(2)
    .setHeader("messageInfo", "Oh dear! An exception.")
    .to("mock:error");

from("seda:a").to("seda:b");

재전송 정책 메서드( 표 6.1. “Redelivery Policy Settings”에 나열된 대로)를 연결하여 재전송 옵션이 지정되고 to() DSL 명령을 사용하여 dead letter channel의 끝점을 지정합니다. onException() 절에서 다른 Java DSL 명령을 호출할 수도 있습니다. 예를 들어 이전 예제에서는 setHeader() 를 호출하여 messageInfo 라는 메시지 헤더에 일부 오류 세부 정보를 기록합니다.

이 예에서는 NullPointerExceptionIOException 예외 유형이 특별히 구성됩니다. 기타 모든 예외 유형은 일반 Exception 예외 인터셉터에서 처리합니다. 기본적으로 Apache Camel은 throw된 예외와 가장 근접하게 일치하는 예외 인터셉터를 적용합니다. 정확한 일치 항목을 찾지 못하면 가장 가까운 기본 유형과 일치하도록 시도합니다. 마지막으로 다른 인터셉터와 일치하지 않는 경우 Exception 유형의 인터셉터는 나머지 모든 예외와 일치합니다.

6.3.14. OnPrepareFailure

교환을 dead letter 큐로 전달하기 전에 onPrepare 옵션을 사용하여 사용자 지정 프로세서가 교환을 준비할 수 있도록 할 수 있습니다. 교환 실패의 원인과 같은 교환에 대한 정보를 추가할 수 있습니다. 예를 들어 다음 프로세서는 예외 메시지와 함께 헤더를 추가합니다.

public class MyPrepareProcessor implements Processor {
    @Override
    public void process(Exchange exchange) throws Exception {
        Exception cause = exchange.getProperty(Exchange.EXCEPTION_CAUGHT, Exception.class);
        exchange.getIn().setHeader("FailedBecause", cause.getMessage());
    }
}

다음과 같이 프로세서를 사용하도록 오류 처리기를 구성할 수 있습니다.

errorHandler(deadLetterChannel("jms:dead").onPrepareFailure(new MyPrepareProcessor()));

그러나 onPrepare 옵션은 기본 오류 처리기를 사용하여 사용할 수도 있습니다.

<bean id="myPrepare"
class="org.apache.camel.processor.DeadLetterChannelOnPrepareTest.MyPrepareProcessor"/>

<errorHandler id="dlc" type="DeadLetterChannel" deadLetterUri="jms:dead" onPrepareFailureRef="myPrepare"/>

6.4. 보장된 제공

6.4.1. 개요

보장된 전달 은 메시지가 메시지 채널에 배치되면 메시징 시스템은 애플리케이션의 일부가 실패하더라도 메시지가 해당 대상에 도달할 것임을 보장합니다. 일반적으로 메시징 시스템은 대상에 전달하기 전에 영구 스토리지에 메시지를 작성하여 그림 6.4. “보장된 제공 패턴” 에 표시된 보장된 전달 패턴을 구현합니다.

그림 6.4. 보장된 제공 패턴

보장된 제공 패턴

6.4.2. 보장된 전달을 지원하는 구성 요소

다음 Apache Camel 구성 요소는 보장된 제공 패턴을 지원합니다.

6.4.3. JMS

JMS에서 deliveryPersistent 쿼리 옵션은 메시지의 영구 스토리지가 활성화되었는지 여부를 나타냅니다. 기본 동작은 영구 전달을 활성화하는 것이므로 일반적으로 이 옵션을 설정할 필요가 없습니다. 보장된 제공의 모든 세부 사항을 구성하려면 JMS 공급자에서 구성 옵션을 설정해야 합니다. 이러한 세부 사항은 사용 중인 JMS 공급자에 따라 다릅니다. 예를 들어 MQSeries, TibCo, BEA, Sonic 등은 모두 보장된 전달을 지원하기 위해 다양한 서비스를 제공합니다.

자세한 내용은 Apache Camel 구성 요소 참조 가이드>에서 Jms 를 참조하십시오.

6.4.4. ActiveMQ

ActiveMQ에서는 메시지 지속성이 기본적으로 활성화됩니다. 버전 5 이후의 ActiveMQ는 AMQ 메시지 저장소를 기본 지속성 메커니즘으로 사용합니다. ActiveMQ에서 메시지 지속성을 전달하는 데 사용할 수 있는 몇 가지 다른 방법이 있습니다.

가장 간단한 옵션( 그림 6.4. “보장된 제공 패턴”와 다름)은 중앙 브로커에서 지속성을 활성화한 다음 신뢰할 수 있는 프로토콜을 사용하여 해당 브로커에 연결하는 것입니다. 메시지를 중앙 브로커로 보낸 후에는 소비자에게 전달이 보장됩니다. 예를 들어 Apache Camel 구성 파일 META-INF/spring/camel-context.xml 에서는 다음과 같이 OpenWire/TCP 프로토콜을 사용하여 중앙 브로커에 연결하도록 ActiveMQ 구성 요소를 구성할 수 있습니다.

<beans ... >
  ...
  <bean id="activemq" class="org.apache.activemq.camel.component.ActiveMQComponent">
    <property name="brokerURL" value="tcp://somehost:61616"/>
  </bean>
  ...
</beans>

메시지가 원격 끝점( 그림 6.4. “보장된 제공 패턴”과 유사)으로 전송되기 전에 로컬로 저장되는 아키텍처를 구현하려는 경우 Apache Camel 애플리케이션에 포함된 브로커를 인스턴스화하여 이 작업을 수행합니다. 이를 달성하는 간단한 방법은 다른 피어 끝점과 통신하기 위해 암시적으로 포함된 브로커를 생성하는 ActiveMQ Peer-to-Peer 프로토콜을 사용하는 것입니다. 예를 들어 camel-context.xml 구성 파일에서 다음과 같이 그룹 GroupA 의 모든 피어에 연결하도록 ActiveMQ 구성 요소를 구성할 수 있습니다.

<beans ... >
  ...
  <bean id="activemq" class="org.apache.activemq.camel.component.ActiveMQComponent">
    <property name="brokerURL" value="peer://GroupA/broker1"/>
  </bean>
  ...
</beans>

여기서 broker1 은 포함된 브로커의 브로커 이름입니다(그룹의 다른 피어는 다른 브로커 이름을 사용해야 함). Peer-to-Peer 프로토콜의 한 가지 제한 기능은 IP 멀티캐스트를 사용하여 해당 그룹의 다른 피어를 찾는 것입니다. 이를 통해 광범위한 영역 네트워크(및 IP 멀티 캐스트가 활성화되지 않은 일부 로컬 영역 네트워크)에서 사용하는 것은 적절하지 않습니다.

ActiveMQ 구성 요소에 포함된 브로커를 생성하는 보다 유연한 방법은 포함된 브로커 인스턴스에 연결하는 ActiveMQ의 VM 프로토콜을 활용하는 것입니다. 필요한 이름의 브로커가 없으면 VM 프로토콜이 자동으로 생성됩니다. 이 메커니즘을 사용하여 사용자 지정 구성으로 포함된 브로커를 생성할 수 있습니다. 예를 들면 다음과 같습니다.

<beans ... >
  ...
  <bean id="activemq" class="org.apache.activemq.camel.component.ActiveMQComponent">
    <property name="brokerURL" value="vm://broker1?brokerConfig=xbean:activemq.xml"/>
  </bean>
  ...
</beans>

여기서 activemq.xml 은 포함된 브로커 인스턴스를 구성하는 ActiveMQ 파일입니다. ActiveMQ 구성 파일 내에서 다음 지속성 메커니즘 중 하나를 활성화하도록 선택할 수 있습니다.

  • AMQ 지속성(기본값) Cryo stat- Cryostat ActiveMQ에 고유하는 빠르고 신뢰할 수 있는 메시지 저장소입니다. 자세한 내용은 amqPersistenceAdapterAMQ Message Store 를 참조하십시오.
  • JDBC 지속성 Cryostat- Cryostat는 JDBC와 호환되는 모든 데이터베이스에 메시지를 저장하기 위해 JDBC를 사용합니다. 자세한 내용은 jdbcPersistenceAdapterActiveMQ 지속성 을 참조하십시오.
  • 저널 지속성 - 롤링 로그 파일에 메시지를 저장하는 빠른 지속성 메커니즘입니다. 자세한 내용은 journalPersistenceAdapterActiveMQ 지속성 을 참조하십시오.
  • KAHA 지속성 관계 - ActiveMQ를 위해 특별히 개발된 지속성 메커니즘. 자세한 내용은 kahaPersistenceAdapterActiveMQ 지속성 을 참조하십시오.

자세한 내용은 Apache Camel 구성 요소 참조 가이드ActiveMQ 를 참조하십시오.

6.4.5. ActiveMQ Journal

ActiveMQ Journal 구성 요소는 여러 동시 생산자가 대기열에 메시지를 작성하지만 활성 소비자가 하나만 있는 특수 사용 사례에 최적화되어 있습니다. 메시지는 롤링 로그 파일에 저장되고 동시 쓰기는 효율성을 높이기 위해 집계됩니다.

6.5. 메시지 버스

6.5.1. 개요

메시지 버스는 다양한 컴퓨팅 플랫폼에서 실행되는 다양한 애플리케이션을 연결할 수 있는 그림 6.5. “메시지 버스 패턴” 에 표시된 메시징 아키텍처를 나타냅니다. 실제로 Apache Camel 및 해당 구성 요소는 메시지 버스를 구성합니다.

그림 6.5. 메시지 버스 패턴

메시지 버스 패턴

메시지 버스 패턴의 다음 기능은 Apache Camel에 반영됩니다.

  • 라우터 자체는 Apache Camel의 공통 통신 인프라의 핵심을 제공합니다. 그러나 일부 메시지 버스 아키텍처와 달리 Apache Camel은 이기종 인프라를 제공합니다. 다양한 전송을 사용하여 메시지를 버스로 전송하고 다양한 메시지 형식을 사용할 수 있습니다.
  • 필요한 경우, Apache Camel은 다양한 전송을 사용하여 메시지 형식을 변환하고 메시지를 전파할 수 있습니다. 실제로 Apache Camel은 어댑터처럼 작동할 수 있으므로 외부 애플리케이션이 메시징 프로토콜을 리팩토링하지 않고도 메시지 버스에 후크할 수 있습니다.

    경우에 따라 어댑터를 외부 애플리케이션에 직접 통합할 수도 있습니다. 예를 들어 Apache CXF를 사용하여 애플리케이션을 개발하는 경우, 이 서비스는 Cryostat-WS 및 CryostatB 매핑을 사용하여 구현되는 경우 다양한 전송 방법을 서비스에 바인딩할 수 있습니다. 이러한 전송 바인딩은 어댑터로 작동합니다.

7장. 메시지 구조

초록

메시지 구성 패턴은 시스템을 통과하는 메시지의 다양한 양식과 기능을 설명합니다.

7.1. 상관관계 식별자

7.1.1. 개요

그림 7.1. “상관관계 식별자 패턴” 에 표시된 상관 관계 식별자 패턴은 비동기 메시징 시스템이 요청 reply 프로토콜을 구현하는 데 사용되는 경우 응답 메시지와 요청 메시지를 일치시키는 방법을 설명합니다. 이 개념의 핵심은 요청 메시지가 고유한 토큰인 요청 ID를 사용하여 생성해야 하며, 요청 메시지를 식별하는 요청 ID 는 일치하는 요청 ID를 포함하는 토큰, 상관 관계 ID 인 토큰을 포함해야 한다는 것입니다.

Apache Camel은 메시지에서 헤더를 가져오거나 설정하여 EIP 패턴의 수정 ID를 지원합니다.

ActiveMQ 또는 JMS 구성 요소로 작업할 때 상관 관계 식별자 헤더를 JMSCorrelationID 라고 합니다. 메시지 교환에 고유한 상관관계 식별자를 추가하여 단일 대화(또는 비즈니스 프로세스)에서 메시지를 함께 상호 연관시킬 수 있습니다. 상관 관계 식별자는 일반적으로 Apache Camel 메시지 헤더에 저장됩니다.

일부 EIP 패턴은 하위 메시지를 회전하고, 이러한 경우 Apache Camel은 소스 교환에 다시 연결되는 키인 Exchange.CORRELATION_ID 를 가진 속성으로 상호 연결 ID를 교환에 추가합니다. 예를 들어, 분할자,멀티 캐스트,수신자 목록유선 탭 EIP는 이 작업을 수행합니다.

그림 7.1. 상관관계 식별자 패턴

상관관계 식별자 패턴

7.2. 이벤트 메시지

7.1. 이벤트 메시지

Camel은 단방향 이벤트 메시지를 나타내기 위해 메시지에서 교환 패턴을 지원하여 InOnly 로 설정할 수 있는 메시지 의 이벤트 메시지를 지원합니다. ??? 그런 다음 Camel Apache Camel 구성 요소 참조 는 기본 전송 또는 프로토콜을 사용하여 이 패턴을 구현합니다.

이벤트 메시지 솔루션

많은 Apache Camel 구성 요소 참조 의 기본 동작은 InOnly(예: JMS,File 또는 SEDA)입니다.

1. InOnly 지정

기본적으로 InOut인 구성 요소를 사용하는 경우 pattern 속성을 사용하여 끝점에 대한 메시지 교환 패턴을 재정의할 수 있습니다.

foo:bar?exchangePattern=InOnly

Camel의 2.0 이후부터 DSL 을 사용하여 메시지 교환 패턴을 지정할 수 있습니다.

Fluent Builders사용

from("mq:someQueue").
  inOnly().
  bean(Foo.class);

또는 명시적 패턴을 사용하여 끝점을 호출할 수 있습니다.

from("mq:someQueue").
  inOnly("mq:anotherQueue");

Spring XML Extensions사용

<route>
    <from uri="mq:someQueue"/>
    <inOnly uri="bean:foo"/>
</route>
<route>
    <from uri="mq:someQueue"/>
    <inOnly uri="mq:anotherQueue"/>
</route>

7.3. 반환 주소

7.3.1. 반환 주소

Apache Camel은 JMSReplyTo 헤더를 사용하여 엔터프라이즈 통합 패턴에서 반환 주소를 지원합니다.

return address solution

예를 들어 InOut 에서 JMS 를 사용하는 경우 구성 요소는 기본적으로 JMSReplyTo 에 지정된 주소로 반환됩니다.

1. 예제

요청자 코드

 getMockEndpoint("mock:bar").expectedBodiesReceived("Bye World");
 template.sendBodyAndHeader("direct:start", "World", "JMSReplyTo", "queue:bar");

Fluent Builders를 사용한 경로

 from("direct:start").to("activemq:queue:foo?preserveMessageQos=true");
 from("activemq:queue:foo").transform(body().prepend("Bye "));
 from("activemq:queue:bar?disableReplyTo=true").to("mock:bar");

Spring XML 확장을사용하는 경로

 <route>
   <from uri="direct:start"/>
   <to uri="activemq:queue:foo?preserveMessageQos=true"/>
 </route>

 <route>
   <from uri="activemq:queue:foo"/>
   <transform>
       <simple>Bye ${in.body}</simple>
   </transform>
 </route>

 <route>
   <from uri="activemq:queue:bar?disableReplyTo=true"/>
   <to uri="mock:bar"/>
 </route>

이 패턴의 전체 예제는 이 JUnit 테스트 사례를참조하십시오.

8장. 메시지 라우팅

초록

메시지 라우팅 패턴은 메시지 채널을 함께 연결하는 다양한 방법을 설명합니다. 여기에는 메시지의 본문을 수정하지 않고 메시지 스트림에 적용할 수 있는 다양한 알고리즘이 포함됩니다.

8.1. 콘텐츠 기반 라우터

8.1.1. 개요

그림 8.1. “컨텐츠 기반 라우터 패턴” 에 표시된 콘텐츠 기반 라우터 를 사용하면 메시지 콘텐츠를 기반으로 메시지를 적절한 대상으로 라우팅할 수 있습니다.

그림 8.1. 컨텐츠 기반 라우터 패턴

콘텐츠 기반 라우터 패턴

8.1.2. Java DSL 예

다음 예제에서는 다양한 서술자 표현식 평가에 따라 입력, seda:a, endpoint에서 seda:b:b:c, seda:d 로 요청을 라우팅하는 방법을 보여줍니다.

RouteBuilder builder = new RouteBuilder() {
    public void configure() {
        from("seda:a").choice()
          .when(header("foo").isEqualTo("bar")).to("seda:b")
          .when(header("foo").isEqualTo("cheese")).to("seda:c")
          .otherwise().to("seda:d");
    }
};

8.1.3. XML 구성 예

다음 예제에서는 XML로 동일한 경로를 구성하는 방법을 보여줍니다.

<camelContext id="buildSimpleRouteWithChoice" xmlns="http://camel.apache.org/schema/spring">
  <route>
    <from uri="seda:a"/>
    <choice>
      <when>
        <xpath>$foo = 'bar'</xpath>
        <to uri="seda:b"/>
      </when>
      <when>
        <xpath>$foo = 'cheese'</xpath>
        <to uri="seda:c"/>
      </when>
      <otherwise>
        <to uri="seda:d"/>
      </otherwise>
    </choice>
  </route>
</camelContext>

8.2. 메시지 필터

8.2.1. 개요

메시지 필터 는 특정 기준에 따라 바람직하지 않은 메시지를 제거하는 프로세서입니다. Apache Camel에서 그림 8.2. “메시지 필터 패턴” 에 표시된 메시지 필터 패턴은 filter() Java DSL 명령으로 구현됩니다. filter() 명령은 필터를 제어하는 단일 서술자 인수를 사용합니다. 서술자가 true 이면 들어오는 메시지가 계속 진행할 수 있으며 서술자가 false 이면 들어오는 메시지가 차단됩니다.

그림 8.2. 메시지 필터 패턴

메시지 필터 패턴

8.2.2. Java DSL 예

다음 예제에서는 foo 헤더에 값이 있는 메시지를 제외한 모든 메시지를 차단하는 끝점, seda:a, to endpoint, seda:b 에서 경로를 생성하는 방법을 보여줍니다.

RouteBuilder builder = new RouteBuilder() {
    public void configure() {
        from("seda:a").filter(header("foo").isEqualTo("bar")).to("seda:b");
    }
};

더 복잡한 필터 서술자를 평가하려면 Cryostat, XQuery 또는 SQL과 같은 지원되는 스크립팅 언어 중 하나를 호출할 수 있습니다( II 부. 라우팅 표현식 및 서술자 언어참조). 다음 예제에서는 name 속성이 Cryostat와 같은 person 요소가 포함된 사용자를 제외한 모든 메시지를 차단하는 경로를 정의합니다.

from("direct:start").
        filter().xpath("/person[@name='James']").
        to("mock:result");

8.2.3. XML 구성 예

다음 예제에서는 XML에서 Cryostat 서술자를 사용하여 경로를 구성하는 방법을 보여줍니다( II 부. 라우팅 표현식 및 서술자 언어참조).

<camelContext id="simpleFilterRoute" xmlns="http://camel.apache.org/schema/spring">
  <route>
    <from uri="seda:a"/>
    <filter>
      <xpath>$foo = 'bar'</xpath>
      <to uri="seda:b"/>
    </filter>
  </route>
  </camelContext>
</filter> 태그 내에 필터링된 끝점 필요

닫는 </filter> 태그 전에 필터링할 끝점(예 : <to uri="seda:b" / > )을 배치하거나 필터가 적용되지 않는지 확인합니다( 2.8+를 생략하면 오류가 발생합니다).

8.2.4. 빈으로 필터링

빈을 사용하여 필터 동작을 정의하는 예는 다음과 같습니다.

from("direct:start")
     .filter().method(MyBean.class, "isGoldCustomer").to("mock:result").end()
     .to("mock:end");

public static class MyBean {
    public boolean isGoldCustomer(@Header("level") String level) {
        return level.equals("gold");
    }
}

8.2.5. stop() 사용

Camel 2.0에서 사용 가능

stop은 모든 메시지를 필터링하는 특수한 유형의 필터입니다. Stop은 서술자 중 하나에서 추가 처리를 중지해야 하는 경우 콘텐츠 기반 라우터에서 사용하기 편리합니다.

다음 예제에서는 메시지 본문에 Bye 라는 메시지가 있는 메시지가 경로에서 더 이상 전파되는 것을 원하지 않습니다. when() 서술자에서 .stop() 을 사용하는 것을 방지합니다.

from("direct:start")
    .choice()
        .when(bodyAs(String.class).contains("Hello")).to("mock:hello")
        .when(bodyAs(String.class).contains("Bye")).to("mock:bye").stop()
        .otherwise().to("mock:other")
    .end()
    .to("mock:result");

8.2.6. 교환이 필터링되었는지 여부를 알고

Camel 2.5부터 사용 가능

메시지 필터 EIP는 필터링되었는지 여부를 나타내는 Exchange에 속성을 추가합니다.

속성에는 CamelFilterMatched 의 문자열 값이 있는 Exchange.FILTER_MATCHED 키가 있습니다. 해당 값은 true 또는 false 를 나타내는 부울 값입니다. 값이 true 이면 Exchange가 필터 블록에서 라우팅되었습니다.

8.3. 수신자 목록

8.3.1. 개요

그림 8.3. “수신자 목록 패턴” 에 표시된 수신자 목록은 수신되는 각 메시지를 여러 다른 대상으로 전송하는 라우터 유형입니다. 또한 수신자 목록은 일반적으로 수신자 목록을 런타임에 계산해야 합니다.

그림 8.3. 수신자 목록 패턴

수신자 목록 패턴

8.3.2. 고정 대상이 있는 수신자 목록

가장 간단한 종류의 수신자 목록은 대상 목록이 수정되고 미리 알려진 위치이며 교환 패턴은 InOnly 입니다. 이 경우 대상 목록을 to() Java DSL 명령으로 연결할 수 있습니다.

참고

여기에 제공된 예제는 고정 목적지가 있는 수신자 목록의 경우 InOnly 교환 패턴(파운전 및 필터 패턴과유사) 에서만 작동합니다. 외부 메시지와 함께 교환 패턴에 대한 수신자 목록을 만들려면 대신 멀티캐스트 패턴을 사용합니다.

8.3.3. Java DSL 예

다음 예제에서는 소비자 끝점, queue:a 에서 고정 대상 목록으로 InOnly 교환을 라우팅하는 방법을 보여줍니다.

from("seda:a").to("seda:b", "seda:c", "seda:d");

8.3.4. XML 구성 예

다음 예제에서는 XML로 동일한 경로를 구성하는 방법을 보여줍니다.

<camelContext id="buildStaticRecipientList" xmlns="http://camel.apache.org/schema/spring">
  <route>
    <from uri="seda:a"/>
    <to uri="seda:b"/>
    <to uri="seda:c"/>
    <to uri="seda:d"/>
  </route>
</camelContext>

8.3.5. 런타임에 계산된 수신자 목록

대부분의 경우 수신자 목록 패턴을 사용하는 경우 수신자 목록을 런타임에 계산해야 합니다. 이렇게 하려면 대상 목록을 유일한 인수로 사용하는 recipientList() 프로세서를 사용합니다. Apache Camel은 목록 인수에 유형 변환기를 적용하므로 대부분의 표준 Java 목록 유형(예: 컬렉션, 목록 또는 배열)을 사용할 수 있어야 합니다. 유형 변환기에 대한 자세한 내용은 34.3절. “붙박임 유형” 을 참조하십시오.

수신자는 동일한 교환 인스턴스의 사본을 수신하고 Apache Camel은 이를 순차적으로 실행합니다.

8.3.6. Java DSL 예

다음 예제에서는 recipientListHeader 라는 메시지 헤더에서 대상 목록을 추출하는 방법을 보여줍니다. 여기서 헤더 값은 끝점 URI의 쉼표로 구분된 목록입니다.

from("direct:a").recipientList(header("recipientListHeader").tokenize(","));

경우에 따라 헤더 값이 목록 유형인 경우 recipientList() 의 인수로 직접 사용할 수 있습니다. 예를 들면 다음과 같습니다.

from("seda:a").recipientList(header("recipientListHeader"));

그러나 이 예제는 기본 구성 요소가 이 특정 헤더를 구문 분석하는 방법에 전적으로 의존합니다. 구성 요소가 헤더를 간단한 문자열로 구문 분석하면 이 예제가 작동하지 않습니다. 헤더는 특정 유형의 Java 목록으로 구문 분석해야 합니다.

8.3.7. XML 구성 예

다음 예제에서는 XML에서 이전 경로를 구성하는 방법을 보여줍니다. 여기서 헤더 값은 엔드포인트 URI의 쉼표로 구분된 목록입니다.

<camelContext id="buildDynamicRecipientList" xmlns="http://camel.apache.org/schema/spring">
  <route>
    <from uri="seda:a"/>
    <recipientList delimiter=",">
      <header>recipientListHeader</header>
    </recipientList>
  </route>
</camelContext>

8.3.8. 병렬로 여러 수신자에게 전송

Camel 2.2에서 사용 가능

수신자 목록 패턴은 병렬Processing 지원하며 이는 splitter 패턴 의 해당 기능과 유사합니다. 병렬 처리 기능을 사용하여 동시에 여러 수신자에게 교환을 보냅니다. 예를 들면 다음과 같습니다.

from("direct:a").recipientList(header("myHeader")).parallelProcessing();

Spring XML에서 병렬 처리 기능은 recipientList 태그의 속성으로 구현됩니다. 예를 들면 다음과 같습니다.

<route>
  <from uri="direct:a"/>
  <recipientList parallelProcessing="true">
    <header>myHeader</header>
  </recipientList>
</route>

8.3.9. 예외 발생 시 중지

Camel 2.2에서 사용 가능

수신자 목록은 수신자 가 실패하는 경우 추가 수신자에게 전송을 중지하는 데 사용할 수 있는 stopOnException 기능을 지원합니다.

from("direct:a").recipientList(header("myHeader")).stopOnException();

그리고 Spring XML은 수신자 목록 태그의 특성입니다.

Spring XML에서 예외에 대한 중지 기능은 recipientList 태그의 속성으로 구현됩니다. 예를 들면 다음과 같습니다.

<route>
  <from uri="direct:a"/>
  <recipientList stopOnException="true">
    <header>myHeader</header>
  </recipientList>
</route>
참고

동일한 경로에 parallelProcessingstopOnException 을 결합할 수 있습니다.

8.3.10. 잘못된 끝점 무시

Camel 2.3부터 사용 가능

수신자 목록 패턴은 무시InvalidEndpoints 옵션을 지원하므로 수신자 목록이 잘못된 엔드포인트를 건너뛸 수 있습니다(outoutslips 패턴 도 이 옵션을 지원합니다). 예를 들면 다음과 같습니다.

from("direct:a").recipientList(header("myHeader")).ignoreInvalidEndpoints();

Spring XML에서는 다음과 같이 recipientList 태그에서 ignoreInvalidEndpoints 특성을 설정하여 이 옵션을 활성화할 수 있습니다.

<route>
  <from uri="direct:a"/>
  <recipientList ignoreInvalidEndpoints="true">
    <header>myHeader</header>
  </recipientList>
</route>

myHeader 에 두 개의 끝점인 direct:foo,xxx:bar 가 포함된 경우를 고려하십시오. 첫 번째 끝점이 유효하고 작동합니다. 두 번째는 유효하지 않으므로 무시됩니다. 잘못된 엔드포인트가 발생할 때마다 INFO 수준에서 Apache Camel 로그를 기록합니다.

8.3.11. 사용자 정의 집계Strategy 사용

Camel 2.2에서 사용 가능

수신자 목록 패턴에 사용자 정의 집계Strategy 를 사용할 수 있습니다. 이 패턴은 목록 의 수신자에서 응답을 집계하는 데 유용합니다. 기본적으로 Apache Camel은 UseLatestAggregationStrategy 집계 전략을 사용하여 마지막으로 수신된 응답만 유지합니다. 보다 정교한 집계 전략의 경우 AggregationStrategy 인터페이스의 자체 구현을 정의할 수 있습니다. 자세한 내용은 8.5절. “수집기” 에서 참조하십시오. 예를 들어 응답 메시지에 사용자 정의 집계 전략 MyOwnAggregationStrategy 를 적용하려면 다음과 같이 Java DSL 경로를 정의할 수 있습니다.

from("direct:a")
    .recipientList(header("myHeader")).aggregationStrategy(new MyOwnAggregationStrategy())
    .to("direct:b");

Spring XML에서는 다음과 같이 사용자 정의 집계 전략을 recipientList 태그의 속성으로 지정할 수 있습니다.

<route>
  <from uri="direct:a"/>
  <recipientList strategyRef="myStrategy">
    <header>myHeader</header>
  </recipientList>
  <to uri="direct:b"/>
</route>

<bean id="myStrategy" class="com.mycompany.MyOwnAggregationStrategy"/>

8.3.12. 사용자 정의 스레드 풀 사용

Camel 2.2에서 사용 가능

이는 parallelProcessing 을 사용하는 경우에만 필요합니다. 기본적으로 Camel은 10개의 스레드가 있는 스레드 풀을 사용합니다. 이는 나중에 스레드 풀 관리 및 구성을 조정할 때 변경될 수 있습니다( Camel 2.2에서 제외).

사용자 정의 집계 전략과 마찬가지로 이를 구성합니다.

8.3.13. 메서드 호출을 수신자 목록으로 사용

metrics 통합을 사용하여 수신자를 제공할 수 있습니다. 예를 들면 다음과 같습니다.

from("activemq:queue:test").recipientList().method(MessageRouter.class, "routeTo");

MessageRouter 8080은 다음과 같이 정의됩니다.

public class MessageRouter {

    public String routeTo() {
        String queueName = "activemq:queue:test2";
        return queueName;
    }
}

8.3.14. receiver list as recipient list

빈이 수신자 목록을 반환하는 메서드에 @RecipientList 주석을 추가하여 수신자 목록으로 작동하도록 할 수 있습니다. 예를 들면 다음과 같습니다.

public class MessageRouter {

    @RecipientList
    public String routeTo() {
        String queueList = "activemq:queue:test1,activemq:queue:test2";
        return queueList;
    }
}

이 경우 경로에 recipientList DSL 명령을 포함하지 마십시오. 경로를 다음과 같이 정의합니다.

from("activemq:queue:test").bean(MessageRouter.class, "routeTo");

8.3.15. 시간 초과 사용

Camel 2.5부터 사용 가능

parallelProcessing 을 사용하는 경우 총 시간 초과 값을 밀리초 단위로 구성할 수 있습니다. 그러면 Camel에서 시간 초과에 도달할 때까지 메시지를 병렬로 처리합니다. 이렇게 하면 하나의 메시지가 느린 경우 처리를 계속할 수 있습니다.

아래 예제에서 수신자 목록 헤더의 값은 direct:a,direct:b,direct:c 이므로 메시지가 3개의 수신자로 전송됩니다. 시간 초과는 250밀리초이며, 이는 마지막 두 메시지만 기간 내에 완료할 수 있음을 의미합니다. 따라서 집계는 문자열 결과인 Cryostat를 생성합니다.

from("direct:start")
    .recipientList(header("recipients"), ",")
    .aggregationStrategy(new AggregationStrategy() {
            public Exchange aggregate(Exchange oldExchange, Exchange newExchange) {
                if (oldExchange == null) {
                    return newExchange;
                }

                String body = oldExchange.getIn().getBody(String.class);
                oldExchange.getIn().setBody(body + newExchange.getIn().getBody(String.class));
                return oldExchange;
            }
        })
        .parallelProcessing().timeout(250)
    // use end to indicate end of recipientList clause
    .end()
    .to("mock:result");

from("direct:a").delay(500).to("mock:A").setBody(constant("A"));

from("direct:b").to("mock:B").setBody(constant("B"));

from("direct:c").to("mock:C").setBody(constant("C"));
참고

시간 초과 기능은 splittermulticastrecipientList 둘 다에서 지원됩니다.

기본적으로 시간 초과가 발생하면 AggregationStrategy 가 호출되지 않습니다. 그러나 전문 버전을 구현할 수 있습니다.

// Java
public interface TimeoutAwareAggregationStrategy extends AggregationStrategy {

    /**
     * A timeout occurred
     *
     * @param oldExchange  the oldest exchange (is <tt>null</tt> on first aggregation as we only have the new exchange)
     * @param index        the index
     * @param total        the total
     * @param timeout      the timeout value in millis
     */
    void timeout(Exchange oldExchange, int index, int total, long timeout);

이를 통해 실제로 필요한 경우 AggregationStrategy 에서 시간 초과를 처리할 수 있습니다.

시간 초과는 합계입니다.

시간 초과는 합계입니다. 즉, X 시간이 지나면 Camel이 기간 내에 완료된 메시지를 집계합니다. 나머지 부분은 취소됩니다. Camel은 첫 번째 인덱스에 대해 TimeoutAwareAggregationStrategy 의 시간 초과 메서드만 호출하여 시간 초과를 초래했습니다.

8.3.16. 발신 메시지에 사용자 정의 처리 적용

받는 사람 끝점 중 하나에 메시지를 보내기 전에 원본 메시지의 단순 복사본인 메시지 복제본을 만듭니다.Before recipientList sends a message to one of the recipient endpoints, it creates a message replica, which is a shallow copy of the original message. 단순 복사본에서는 원본 메시지의 헤더와 페이로드가 참조로만 복사됩니다. 각 새 복사본에는 해당 요소의 자체 인스턴스가 포함되어 있지 않습니다. 결과적으로 메시지의 부분 복사본이 연결되며 다른 엔드포인트로 라우팅할 때 사용자 지정 처리를 적용할 수 없습니다.

복제본이 끝점으로 전송되기 전에 각 메시지 복제본에서 일부 사용자 지정 처리를 수행하려면 recipientList 절에서 onPrepare DSL 명령을 호출할 수 있습니다. onPrepare 명령은 메시지가 부분 복사된 직후 그리고 메시지가 끝점으로 디스패치되기 직전에 사용자 지정 프로세서를 삽입합니다. 예를 들어 다음 경로에서 각 수신자 끝점에 대한 메시지 복제본에서 CustomProc 프로세서가 호출됩니다.

from("direct:start")
  .recipientList().onPrepare(new CustomProc());

onPrepare DSL 명령의 일반적인 사용 사례는 메시지의 일부 또는 모든 요소의 깊은 복사본을 수행하는 것입니다. 이를 통해 각 메시지 복제본을 다른 사용자와 독립적으로 수정할 수 있습니다. 예를 들어 다음 CustomProc 프로세서 클래스는 메시지 본문의 깊은 복사본을 수행합니다. 여기서 메시지 본문은 유형인 BodyType.deepCopy()로 추정되고 깊은 복사는 메서드인 BodyType.deepCopy() 에 의해 수행됩니다.

// Java
import org.apache.camel.*;
...
public class CustomProc implements Processor {

    public void process(Exchange exchange) throws Exception {
        BodyType body = exchange.getIn().getBody(BodyType.class);

        // Make a _deep_ copy of of the body object
        BodyType clone =  BodyType.deepCopy();
        exchange.getIn().setBody(clone);

        // Headers and attachments have already been
        // shallow-copied. If you need deep copies,
        // add some more code here.
    }
}

8.3.17. 옵션

recipientList DSL 명령은 다음 옵션을 지원합니다.

이름

기본값

설명

구분 기호

,

Expression에서 여러 끝점을 반환한 경우 사용되는 구분 기호입니다.

strategyRef

 

수신자의 응답을 8.3절. “수신자 목록” 에서 보내는 단일 발신 메시지로 어셈블하는 데 사용되는 집계Strategy 를 나타냅니다. 기본적으로 Camel은 마지막 응답을 발신 메시지로 사용합니다.

strategyMethodName

 

이 옵션을 사용하면 Cryostat를 AggregationStrategy 로 사용할 메서드 이름을 명시적으로 지정할 수 있습니다.

strategyMethodAllowNull

false

이 옵션은 Cryostat를 AggregationStrategy 로 사용할 때 사용할 수 있습니다. false 인 경우 보강할 데이터가 없는 경우 집계 방법이 사용되지 않습니다. true 인 경우 보강할 데이터가 없는 경우 oldExchangenull 값이 사용됩니다.

parallelProcessing

false

Camel 2.2: 수신자에게 메시지를 전송하는 경우 동시에 발생합니다. 호출자 스레드는 계속 진행하기 전에 모든 메시지가 완전히 처리될 때까지 대기합니다. 동시에 발생하는 수신자의 응답을 전송 및 처리하는 경우에만 해당합니다.

parallelAggregate

false

활성화하면 AggregationStrategy집계 메서드를 동시에 호출할 수 있습니다. 이를 위해서는 스레드로부터 안전한 AggregationStrategy 를 구현해야 합니다. 기본적으로 이 옵션은 false 입니다. 즉, Camel이 집계 메서드에 자동으로 호출을 동기화합니다. 그러나 일부 사용 사례에서는 AggregationStrategy 를 스레드로부터 안전한 것으로 구현하고 이 옵션을 true 로 설정하여 성능을 향상시킬 수 있습니다.

executorServiceRef

 

Camel 2.2: 병렬 처리에 사용할 사용자 지정 스레드 풀을 나타냅니다. 이 옵션을 설정하면 병렬 처리가 자동으로 표시되고 해당 옵션도 활성화할 필요가 없습니다.

stopOnException

false

Camel 2.2: 예외가 발생한 경우 즉시 처리를 중지해야 하는지의 여부입니다. 비활성화된 경우 Camel은 실패했는지에 관계없이 모든 수신자에게 메시지를 보냅니다. 이를 처리하는 방법을 완전히 제어하는 AggregationStrategy 클래스에서 예외를 처리할 수 있습니다.

ignoreInvalidEndpoints

false

Camel 2.3: 엔드포인트 uri를 해결할 수 없는 경우 무시해야 합니다. 그렇지 않으면 Camel에서 엔드포인트 uri가 유효하지 않음을 나타내는 예외가 throw됩니다.

스트리밍

false

Camel 2.5: 활성화하면 Camel이 주문되지 않은 응답(예: 다시 들어오는 순서)을 처리합니다. 비활성화된 경우 Camel은 지정된 표현식과 동일한 순서로 응답을 처리합니다.

timeout

 

Camel 2.5: 밀리 초 단위로 지정된 총 타임아웃을 설정합니다. 8.3절. “수신자 목록” 에서 지정된 기간 내에 모든 응답을 보내고 처리할 수 없는 경우 시간 초과 트리거와 8.3절. “수신자 목록” 가 중단되고 계속됩니다. AggregationStrategy 를 제공하면 시간 초과 방법이 호출됩니다.

onPrepareRef

 

Camel 2.8: 각 수신자가 수신하는 교환 사본을 준비하기 위해 사용자 지정 프로세서를 참조합니다. 이를 통해 필요한 경우 메시지 페이로드를 깊이 복제하는 등 사용자 지정 논리를 수행할 수 있습니다.

shareUnitOfWork

false

Camel 2.8: 작업 단위를 공유해야 하는지 여부입니다. 자세한 내용은 8.4절. “Splitter” 에서 동일한 옵션을 참조하십시오.

cacheSize

0

Camel 2.13.1/2.12.4: 라우팅 슬립에서 재사용할 생산자를 캐시하는 ProducerCache 의 캐시 크기를 구성할 수 있습니다. 기본적으로는 기본적으로 0인 기본 캐시 크기를 사용합니다. 값을 -1로 설정하면 캐시를 모두 해제할 수 있습니다.

8.3.18. 받는 사람 목록에서 교환 패턴 사용

기본적으로 수신자 목록은 현재 교환 패턴을 사용합니다. 그러나 다른 교환 패턴을 사용하여 받는 사람에게 메시지를 보낼 수 있는 경우는 몇 가지 있을 수 있습니다.

예를 들어 InOnly 경로로 시작하는 경로가 있을 수 있습니다. 이제 받는 사람 목록과 함께 InOut 교환 패턴을 사용하려면 수신자 끝점에서 직접 교환 패턴을 구성해야 합니다.

다음 예제에서는 새 파일이 InOnly로 시작되고 수신자 목록으로 라우팅되는 경로를 보여줍니다. InOut을 ActiveMQ(JMS) 끝점과 함께 사용하려면 exchangePattern을 InOut 옵션과 동일하게 사용하여 지정해야 합니다. 그러나 응답 형식은 JMS 요청 또는 응답을 계속 라우팅하므로 응답은 outbox 디렉터리에 파일로 저장됩니다.

from("file:inbox")
  // the exchange pattern is InOnly initially when using a file route
  .recipientList().constant("activemq:queue:inbox?exchangePattern=InOut")
  .to("file:outbox");
참고

InOut 교환 패턴은 시간 초과 중에 응답을 받아야 합니다. 그러나 응답이 수신되지 않으면 실패합니다.

8.4. Splitter

8.4.1. 개요

splitter 는 들어오는 메시지를 일련의 발신 메시지로 분할하는 라우터 유형입니다. 발신 메시지의 각 메시지에는 원본 메시지의 일부가 포함되어 있습니다. Apache Camel에서 그림 8.4. “Splitter 패턴” 에 표시된 splitter 패턴은 split() Java DSL 명령으로 구현됩니다.

그림 8.4. Splitter 패턴

Splitter 패턴

Apache Camel splitter는 다음과 같이 실제로 두 가지 패턴을 지원합니다.

  • 단순 분할 기 Cryostat-반드기 패턴을 자체적으로 구현합니다.
  • Splitter/aggregator kafka- Cryostat는 메시지 조각이 처리된 후 메시지의 조각이 다시 조합되도록 집계기 패턴과 함께 분할 패턴을 결합합니다.

splitter가 원본 메시지를 여러 부분으로 분리하기 전에 원본 메시지의 부분 복사본을 만듭니다. 단순 복사본에서는 원본 메시지의 헤더와 페이로드가 참조로만 복사됩니다. splitter는 결과 메시지 부분을 다른 끝점으로 라우팅하지 않지만 분할 메시지의 일부는 보조 라우팅을 받을 수 있습니다.

메시지 부분은 부분 복사본이므로 원래 메시지에 연결된 상태로 유지됩니다. 따라서 독립적으로 수정할 수 없습니다. 일련의 엔드포인트로 라우팅하기 전에 메시지 부분의 다른 사본에 사용자 지정 논리를 적용하려면 splitter 절에서 onPrepareRef DSL 옵션을 사용하여 원래 메시지의 깊은 복사본을 만들어야 합니다. 옵션 사용에 대한 자세한 내용은 “옵션” 을 참조하십시오.

8.4.2. Java DSL 예

다음 예제에서는 들어오는 메시지의 각 행을 별도의 발신 메시지로 변환하여 메시지를 분할하는 seda:a 에서 seda:b 로 경로를 정의합니다.

RouteBuilder builder = new RouteBuilder() {
    public void configure() {
        from("seda:a")
          .split(bodyAs(String.class).tokenize("\n"))
          .to("seda:b");
    }
};

splitter는 모든 표현식 언어를 사용할 수 있으므로 Cryostat, XQuery 또는 SQL과 같은 지원되는 스크립팅 언어를 사용하여 메시지를 분할할 수 있습니다( II 부. 라우팅 표현식 및 서술자 언어참조). 다음 예제에서는 들어오는 메시지에서 bar 요소를 추출하여 별도의 발신 메시지에 삽입합니다.

from("activemq:my.queue")
  .split(xpath("//foo/bar"))
  .to("file://some/directory")

8.4.3. XML 구성 예

다음 예제에서는 Cryostat 스크립팅 언어를 사용하여 XML로 splitter 경로를 구성하는 방법을 보여줍니다.

<camelContext id="buildSplitter" xmlns="http://camel.apache.org/schema/spring">
    <route>
      <from uri="seda:a"/>
      <split>
        <xpath>//foo/bar</xpath>
        <to uri="seda:b"/>
      </split>
    </route>
</camelContext>

XML DSL에서 tokenize 표현식을 사용하여 토큰을 사용하여 본문 또는 헤더를 분할할 수 있습니다. 여기서 tokenize 표현식은 tokenize 요소를 사용하여 정의됩니다. 다음 예에서 메시지 본문은 \n 구분 기호 문자를 사용하여 토큰화됩니다. 정규식 패턴을 사용하려면 tokenize 요소에서 regex=true 를 설정합니다.

<camelContext xmlns="http://camel.apache.org/schema/spring">
    <route>
        <from uri="direct:start"/>
        <split>
            <tokenize token="\n"/>
            <to uri="mock:result"/>
        </split>
    </route>
    </camelContext>

8.4.4. 행 그룹으로 분할

큰 파일을 1000 줄의 청크로 분할하려면 Java DSL에서 다음과 같이 splitter 경로를 정의할 수 있습니다.

from("file:inbox")
    .split().tokenize("\n", 1000).streaming()
       .to("activemq:queue:order");

tokenize 의 두 번째 인수는 단일 청크로 그룹화해야 하는 행 수를 지정합니다. streaming() 절에서는 splitter에서 한 번에 전체 파일을 읽지 않도록 지시합니다(파일이 클 경우 성능이 훨씬 향상됩니다).

다음과 같이 XML DSL에 동일한 경로를 정의할 수 있습니다.

<route>
  <from uri="file:inbox"/>
  <split streaming="true">
    <tokenize token="\n" group="1000"/>
    <to uri="activemq:queue:order"/>
  </split>
</route>

group 옵션을 사용하는 경우 출력은 항상 java.lang.String 유형입니다.

8.4.5. 첫 번째 항목 건너뛰기

메시지의 첫 번째 항목을 건너뛰려면 skipFirst 옵션을 사용하면 됩니다.

Java DSL에서 tokenize 매개변수 true 에서 세 번째 옵션을 설정합니다.

from("direct:start")
 // split by new line and group by 3, and skip the very first element
      .split().tokenize("\n", 3, true).streaming()
         .to("mock:group");

다음과 같이 XML DSL에 동일한 경로를 정의할 수 있습니다.

<route>
  <from uri="file:inbox"/>
    <split streaming="true">
    <tokenize token="\n" group="1000" skipFirst="true" />
    <to uri="activemq:queue:order"/>
  </split>
</route>

8.4.6. Splitter 응답

splitter에 들어오는 교환에 In Out 메시지 교환 패턴(즉, 응답이 예상)이 있는 경우 splitter는 메시지 슬롯의 응답 메시지로 원본 입력 메시지의 복사본을 반환합니다. 자체 집계 전략을 구현하여 이 기본 동작을 재정의할 수 있습니다.

8.4.7. 병렬 실행

결과적인 메시지 조각을 병렬로 실행하려는 경우 병렬 처리 옵션을 활성화하여 메시지 조각을 처리하도록 스레드 풀을 인스턴스화할 수 있습니다. 예를 들면 다음과 같습니다.

XPathBuilder xPathBuilder = new XPathBuilder("//foo/bar");
from("activemq:my.queue").split(xPathBuilder).parallelProcessing().to("activemq:my.parts");

병렬 분할기에서 사용되는 기본 ThreadPoolExecutor 를 사용자 지정할 수 있습니다. 예를 들어 다음과 같이 Java DSL에서 사용자 지정 executor를 지정할 수 있습니다.

XPathBuilder xPathBuilder = new XPathBuilder("//foo/bar");
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(8, 16, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue());
from("activemq:my.queue")
  .split(xPathBuilder)
  .parallelProcessing()
  .executorService(threadPoolExecutor)
  .to("activemq:my.parts");

다음과 같이 XML DSL에서 사용자 지정 executor를 지정할 수 있습니다.

<camelContext xmlns="http://camel.apache.org/schema/spring">
  <route>
    <from uri="direct:parallel-custom-pool"/>
    <split executorServiceRef="threadPoolExecutor">
      <xpath>/invoice/lineItems</xpath>
      <to uri="mock:result"/>
    </split>
  </route>
</camelContext>

<bean id="threadPoolExecutor" class="java.util.concurrent.ThreadPoolExecutor">
  <constructor-arg index="0" value="8"/>
  <constructor-arg index="1" value="16"/>
  <constructor-arg index="2" value="0"/>
  <constructor-arg index="3" value="MILLISECONDS"/>
  <constructor-arg index="4"><bean class="java.util.concurrent.LinkedBlockingQueue"/></constructor-arg>
</bean>

8.4.8. 빈을 사용하여 분할 수행

splitter는 임의의 표현식을 사용하여 분할을 수행할 수 있으므로 method() 표현식을 호출하여 빈을 사용하여 분할을 수행할 수 있습니다. Cryostat는 java.util.Collection,java.util.Iterator 또는 배열과 같은 반복 가능한 값을 반환해야 합니다.

다음 경로는 my CryostatterBean -20 instances에서 메서드를 호출하는 method() 표현식을 정의합니다.

from("direct:body")
        // here we use a POJO bean mySplitterBean to do the split of the payload
        .split()
        .method("mySplitterBean", "splitBody")
        .to("mock:result");
from("direct:message")
        // here we use a POJO bean mySplitterBean to do the split of the message
        // with a certain header value
        .split()
        .method("mySplitterBean", "splitMessage")
        .to("mock:result");

여기서 my CryostatterBean 은 다음과 같이 정의된 My CryostatterBean 클래스의 인스턴스입니다.

public class MySplitterBean {

    /**
     * The split body method returns something that is iteratable such as a java.util.List.
     *
     * @param body the payload of the incoming message
     * @return a list containing each part split
     */
    public List<String> splitBody(String body) {
        // since this is based on an unit test you can of couse
        // use different logic for splitting as {router} have out
        // of the box support for splitting a String based on comma
        // but this is for show and tell, since this is java code
        // you have the full power how you like to split your messages
        List<String> answer = new ArrayList<String>();
        String[] parts = body.split(",");
        for (String part : parts) {
            answer.add(part);
        }
        return answer;
    }

    /**
     * The split message method returns something that is iteratable such as a java.util.List.
     *
     * @param header the header of the incoming message with the name user
     * @param body the payload of the incoming message
     * @return a list containing each part split
     */
    public List<Message> splitMessage(@Header(value = "user") String header, @Body String body) {
        // we can leverage the Parameter Binding Annotations
        // http://camel.apache.org/parameter-binding-annotations.html
        // to access the message header and body at same time,
        // then create the message that we want, splitter will
        // take care rest of them.
        // *NOTE* this feature requires {router} version >= 1.6.1
        List<Message> answer = new ArrayList<Message>();
        String[] parts = header.split(",");
        for (String part : parts) {
            DefaultMessage message = new DefaultMessage();
            message.setHeader("user", part);
            message.setBody(body);
            answer.add(message);
        }
        return answer;
    }
}

Splitter EIP와 함께 CryostatIO Cryostatter 오브젝트를 사용하면 전체 콘텐츠를 메모리에 읽지 않도록 스트림 모드를 사용하여 큰 페이로드를 분할할 수 있습니다. 다음 예제에서는 classpath에서 로드된 매핑 파일을 사용하여 Cryostat IO Cryostatter 오브젝트를 설정하는 방법을 보여줍니다.

참고

Camel 2.18의 새로운 클래스입니다. Camel 2.17에서는 사용할 수 없습니다.

BeanIOSplitter splitter = new BeanIOSplitter();
   splitter.setMapping("org/apache/camel/dataformat/beanio/mappings.xml");
   splitter.setStreamName("employeeFile");

    // Following is a route that uses the beanio data format to format CSV data
    // in Java objects:
    from("direct:unmarshal")
        // Here the message body is split to obtain a message for each row:
         .split(splitter).streaming()
         .to("log:line")
         .to("mock:beanio-unmarshal");

다음 예제에서는 오류 처리기를 추가합니다.

BeanIOSplitter splitter = new BeanIOSplitter();
   splitter.setMapping("org/apache/camel/dataformat/beanio/mappings.xml");
   splitter.setStreamName("employeeFile");
   splitter.setBeanReaderErrorHandlerType(MyErrorHandler.class);
   from("direct:unmarshal")
      .split(splitter).streaming()
      .to("log:line")
      .to("mock:beanio-unmarshal");

8.4.9. 속성 교환

다음 속성은 각 분할 교환에 대해 설정됩니다.

헤더typedescription

CamelSplitIndex

int

Apache Camel 2.0: 분할되는 각 Exchange에 대해 증가되는 분할 카운터입니다. 카운터는 0부터 시작합니다.

CamelSplitSize

int

Apache Camel 2.0: 분할된 총 교환 수입니다. 이 헤더는 스트림 기반 분할에는 적용되지 않습니다.

CamelSplitComplete

boolean

Apache Camel 2.4: 이 교환이 마지막인지 여부입니다.

8.4.10. Splitter/aggregator 패턴

개별 조각 처리가 완료된 후 메시지 조각을 단일 교환으로 다시 집계하는 것이 일반적인 패턴입니다. 이 패턴을 지원하기 위해 split() DSL 명령을 사용하면 AggregationStrategy 오브젝트를 두 번째 인수로 제공할 수 있습니다.

8.4.11. Java DSL 예

다음 예제에서는 모든 메시지 조각이 처리된 후 사용자 정의 집계 전략을 사용하여 분할 메시지를 다시 가져오는 방법을 보여줍니다.

from("direct:start")
    .split(body().tokenize("@"), new MyOrderStrategy())
        // each split message is then send to this bean where we can process it
        .to("bean:MyOrderService?method=handleOrder")
        // this is important to end the splitter route as we do not want to do more routing
        // on each split message
    .end()
    // after we have split and handled each message we want to send a single combined
    // response back to the original caller, so we let this bean build it for us
    // this bean will receive the result of the aggregate strategy: MyOrderStrategy
    .to("bean:MyOrderService?method=buildCombinedResponse")

8.4.12. 집계Strategy 구현

이전 경로에 사용되는 사용자 정의 집계 전략 MyOrderStrategy 는 다음과 같이 구현됩니다.

/**
 * This is our own order aggregation strategy where we can control
 * how each split message should be combined. As we do not want to
 * lose any message, we copy from the new to the old to preserve the
 * order lines as long we process them
 */
public static class MyOrderStrategy implements AggregationStrategy {

    public Exchange aggregate(Exchange oldExchange, Exchange newExchange) {
        // put order together in old exchange by adding the order from new exchange

        if (oldExchange == null) {
            // the first time we aggregate we only have the new exchange,
            // so we just return it
            return newExchange;
        }

        String orders = oldExchange.getIn().getBody(String.class);
        String newLine = newExchange.getIn().getBody(String.class);

        LOG.debug("Aggregate old orders: " + orders);
        LOG.debug("Aggregate new order: " + newLine);

        // put orders together separating by semi colon
        orders = orders + ";" + newLine;
        // put combined order back on old to preserve it
        oldExchange.getIn().setBody(orders);

        // return old as this is the one that has all the orders gathered until now
        return oldExchange;
    }
}

8.4.13. 스트림 기반 처리

병렬 처리가 활성화되면 이론적으로 이전 메시지 조각이 이전 문서보다 먼저 집계할 수 있습니다. 즉, 메시지 조각이 순서대로 수집기에 도달할 수 있습니다. 기본적으로 분할자 구현은 메시지를 수집기로 전달하기 전에 메시지를 원래 순서로 다시 정렬하므로 이러한 상황이 발생하지 않습니다.

메시지 조각을 준비한 즉시 집계하려는 경우 다음과 같이 스트리밍 옵션을 활성화할 수 있습니다.

from("direct:streaming")
  .split(body().tokenize(","), new MyOrderStrategy())
    .parallelProcessing()
    .streaming()
    .to("activemq:my.parts")
  .end()
  .to("activemq:all.parts");

다음과 같이 스트리밍에 사용할 사용자 지정 Cryostat를 제공할 수도 있습니다.

// Java
import static org.apache.camel.builder.ExpressionBuilder.beanExpression;
...
from("direct:streaming")
     .split(beanExpression(new MyCustomIteratorFactory(),  "iterator"))
     .streaming().to("activemq:my.parts")
스트리밍 및 Cryostat

Cryostat와 함께 스트리밍 모드를 사용할 수 없습니다. Cryostat에는 메모리에 전체 Cryostat XML 문서가 필요합니다.

8.4.14. XML로 스트림 기반 처리

들어오는 메시지가 매우 큰 XML 파일인 경우 스트리밍 모드에서 tokenize XML 하위 명령을 사용하여 메시지를 가장 효율적으로 처리할 수 있습니다.

예를 들어 순서 요소 시퀀스가 포함된 큰 XML 파일이 있는 경우 다음과 같은 경로를 사용하여 파일을 주문 요소로 분할할 수 있습니다.

from("file:inbox")
  .split().tokenizeXML("order").streaming()
  .to("activemq:queue:order");

XML에서 다음과 같은 경로를 정의하여 동일한 작업을 수행할 수 있습니다.

<route>
  <from uri="file:inbox"/>
  <split streaming="true">
    <tokenize token="order" xml="true"/>
    <to uri="activemq:queue:order"/>
  </split>
</route>

토큰 요소의 enclosing (ancestor) 요소 중 하나에 정의된 네임스페이스에 액세스해야 하는 경우가 많습니다. 네임스페이스 정의를 상속하려는 요소를 지정함으로써 ancestor 요소 중 하나에서 네임스페이스 정의를 토큰 요소로 복사할 수 있습니다.

Java DSL에서 ancestor 요소를 tokenize XML 의 두 번째 인수로 지정합니다. 예를 들어, enclosing orders 요소에서 네임스페이스 정의를 상속하려면 다음을 수행합니다.

from("file:inbox")
  .split().tokenizeXML("order", "orders").streaming()
  .to("activemq:queue:order");

XML DSL에서 inheritNamespaceTagName 특성을 사용하여 ancestor 요소를 지정합니다. 예를 들면 다음과 같습니다.

<route>
  <from uri="file:inbox"/>
  <split streaming="true">
    <tokenize token="order"
              xml="true"
              inheritNamespaceTagName="orders"/>
    <to uri="activemq:queue:order"/>
  </split>
</route>

8.4.15. 옵션

분할 DSL 명령은 다음 옵션을 지원합니다.

이름

기본값

설명

strategyRef

 

하위 메시지의 응답을 8.4절. “Splitter” 에서 보내는 단일 메시지로 어셈블하는 데 사용되는 집계Strategy 를 나타냅니다. 기본적으로 사용되는 항목에 대해서는 아래 분할자 반환의 제목 섹션 을 참조하십시오.

strategyMethodName

 

이 옵션을 사용하면 Cryostat를 AggregationStrategy 로 사용할 메서드 이름을 명시적으로 지정할 수 있습니다.

strategyMethodAllowNull

false

이 옵션은 Cryostat를 AggregationStrategy 로 사용할 때 사용할 수 있습니다. false 인 경우 보강할 데이터가 없는 경우 집계 방법이 사용되지 않습니다. true 인 경우 보강할 데이터가 없는 경우 oldExchangenull 값이 사용됩니다.

parallelProcessing

false

이 옵션을 사용하면 하위 메시지 처리가 동시에 수행됩니다. 호출자 스레드는 계속 진행하기 전에 모든 하위 메시지가 완전히 처리될 때까지 대기합니다.

parallelAggregate

false

활성화하면 AggregationStrategy집계 메서드를 동시에 호출할 수 있습니다. 이를 위해서는 스레드로부터 안전한 AggregationStrategy 를 구현해야 합니다. 기본적으로 이 옵션은 false 입니다. 즉, Camel이 집계 메서드에 자동으로 호출을 동기화합니다. 그러나 일부 사용 사례에서는 AggregationStrategy 를 스레드로부터 안전한 것으로 구현하고 이 옵션을 true 로 설정하여 성능을 향상시킬 수 있습니다.

executorServiceRef

 

병렬 처리에 사용할 사용자 지정 스레드 풀을 나타냅니다.Indicates to a custom Thread Pool to be used for parallel processing. 이 옵션을 설정하면 병렬 처리가 자동으로 표시되고 해당 옵션도 활성화할 필요가 없습니다.

stopOnException

false

Camel 2.2: 예외가 발생한 경우 즉시 처리를 중지해야 하는지의 여부입니다. disable인 경우 Camel은 실패했는지에 관계없이 하위 메시지를 계속 분할하고 처리합니다. 이를 처리하는 방법을 완전히 제어하는 AggregationStrategy 클래스에서 예외를 처리할 수 있습니다.

스트리밍

false

Camel이 활성화된 경우 Camel은 스트리밍 방식으로 분할되므로 입력 메시지를 청크로 분할합니다. 이렇게 하면 메모리 오버헤드가 줄어듭니다. 예를 들어 큰 메시지를 분할하는 경우 스트리밍을 활성화하는 것이 좋습니다. 스트리밍이 활성화되면 하위 메시지 응답이 순서대로 집계됩니다(예: 반환 순서에 따라). 비활성화된 경우 Camel은 분할된 위치와 동일한 순서로 하위 메시지 응답을 처리합니다.

timeout

 

Camel 2.5: 밀리 초 단위로 지정된 총 타임아웃을 설정합니다. 8.3절. “수신자 목록” 에서 지정된 기간 내에 모든 응답을 분할하고 처리할 수 없는 경우 시간 초과 트리거와 8.4절. “Splitter” 가 중단되고 계속됩니다. AggregationStrategy 를 제공하면 시간 초과 방법이 호출됩니다.

onPrepareRef

 

Camel 2.8: 처리되기 전에 교환의 하위 메시지를 준비하기 위해 사용자 지정 프로세서를 참조합니다. 이를 통해 필요한 경우 메시지 페이로드를 깊이 복제하는 등 사용자 지정 논리를 수행할 수 있습니다.

shareUnitOfWork

false

Camel 2.8: 작업 단위를 공유해야 하는지 여부입니다. 자세한 내용은 아래를 참조하십시오.

8.5. 수집기

8.5.1. 개요

그림 8.5. “수집기 패턴” 에 표시된 수집기 패턴을 사용하면 관련 메시지 배치를 단일 메시지에 결합할 수 있습니다.

그림 8.5. 수집기 패턴

수집기 패턴

수집기 동작을 제어하기 위해 Apache Camel을 사용하면 다음과 같이 엔터프라이즈 통합 패턴에 설명된 속성을 지정할 수 있습니다.

  • 상관 관계 표현식 밀리초-단순으로 집계해야 하는 메시지를 결정합니다. 상관관계 표현식은 들어오는 각 메시지에 대해 평가되어 상관관계 키를 생성합니다. 그런 다음 동일한 상관 관계 키를 가진 들어오는 메시지는 동일한 일괄 처리로 그룹화됩니다. 예를 들어 들어오는 모든 메시지를 단일 메시지로 집계하려면 상수 표현식을 사용할 수 있습니다.
  • completeness 조건 Cryo stat- Cryostat 메시지의 일괄 처리가 완료된 시기를 결정합니다. 이를 간단한 크기 제한으로 지정하거나 일반적으로 배치가 완료되면 플래그를 지정하는 서술자 조건을 지정할 수 있습니다.
  • 집계 알고리즘은 단일 상관 키의 메시지 교환을 단일 메시지 교환으로 결합합니다.

예를 들어 초당 Cryostat 메시지를 수신하는 주식 시장 데이터 시스템을 고려해 보십시오. GUI 툴이 이러한 대규모 업데이트 속도로 대처할 수 없는 경우 메시지 흐름을 제한해야 할 수 있습니다. 들어오는 주식 견적은 최신 견적을 선택하고 이전 가격을 폐기하여 간단히 집계 할 수 있습니다. (히스토리 중 일부를 캡처하려는 경우 delta 처리 알고리즘을 적용할 수 있습니다.)

참고

이제 Aggregator가 자세한 정보를 포함하는 ManagedAggregateProcessorMBean 을 사용하여 Cryostat에 등록되었습니다. 이를 통해 집계 컨트롤러를 사용하여 제어할 수 있습니다.

8.5.2. 수집기 작동 방식

그림 8.6. “수집기 구현” 집계기가 작동하는 방식에 대한 개요를 보여줍니다. A, B, C 또는 D와 같은 상관관계 키를 갖는 교환 스트림이 있다고 가정하면 됩니다.

그림 8.6. 수집기 구현

메시지 라우팅 02

그림 8.6. “수집기 구현” 에 표시된 교환의 수신 스트림은 다음과 같이 처리됩니다.

  1. Corre lator 는 상관 관계 키를 기반으로 교환 정렬을 담당합니다. 들어오는 각 교환에 대해 상관관계 표현식이 평가되어 상관 관계 키를 생성합니다. 예를 들어 그림 8.6. “수집기 구현” 에 표시된 교환의 경우 상관 관계 키는 A로 평가됩니다.
  2. 집계 전략은 동일한 상관 관계 키를 사용하여 교환을 병합합니다. 새로운 교환인 A가 들어오면 집계 리포지토리에서 해당 집계 교환, A'를 조회하여 새 교환과 결합합니다.

    특정 집계 사이클이 완료될 때까지 들어오는 교환은 해당 집계 교환과 지속적으로 집계됩니다. 집계 주기는 완료 메커니즘 중 하나에 의해 종료될 때까지 지속됩니다.

    참고

    Camel 2.16에서 새로운 XSLT 집계 전략을 사용하면 두 개의 메시지를 XSLT 파일과 병합할 수 있습니다. toolbox에서 AggregationStrategies.xslt() 파일에 액세스할 수 있습니다.

  3. 완료 서술자가 집계기에 지정된 경우 집계 교환은 경로의 다음 프로세서로 전송할 준비가 되었는지 여부를 확인하기 위해 테스트됩니다. 처리는 다음과 같이 계속됩니다.

    • 완료되면 집계 교환은 경로의 마지막 부분에 의해 처리됩니다. 이에 대한 두 가지 대체 모델이 있습니다. 동기 (기본값)는 호출 스레드를 차단하거나 비동기 ( 병렬 처리가 활성화된 경우)를 실행자 스레드 풀( 그림 8.6. “수집기 구현”에 표시)에 제출합니다.
    • 완료되지 않으면 집계 교환이 다시 집계 리포지토리에 저장됩니다.
  4. 동기 완료 테스트와 동시에 completionTimeout 옵션 또는 completionInterval 옵션을 활성화 하여 비동기 완료 테스트를 활성화할 수 있습니다. 이러한 완료 테스트는 별도의 스레드에서 실행되며 완료 테스트가 충족될 때마다 해당 교환은 완료로 표시되고 경로의 후자 부분에 의해 처리됩니다(행 처리 활성화 여부에 따라 동기적으로 또는 비동기적으로).
  5. 병렬 처리가 활성화된 경우 스레드 풀은 경로의 후자 부분에서 교환 처리를 담당합니다. 기본적으로 이 스레드 풀에는 10개의 스레드가 포함되어 있지만 풀(“스레드 옵션”)을 사용자 정의할 수 있습니다.

8.5.3. Java DSL 예

다음 예제에서는 UseLatestAggregationStrategy 집계 전략을 사용하여 동일한 Cryostat Symbol 헤더 값으로 교환을 집계합니다. 지정된 symbol 값에 대해 해당 상관 관계 키와 마지막 교환이 수신된 이후 3초 이상 경과하면 집계된 교환은 완료된 것으로 간주되고 mock 엔드포인트로 전송됩니다.

from("direct:start")
    .aggregate(header("id"), new UseLatestAggregationStrategy())
        .completionTimeout(3000)
    .to("mock:aggregated");

8.5.4. XML DSL 예

다음 예제에서는 XML로 동일한 경로를 구성하는 방법을 보여줍니다.

<camelContext xmlns="http://camel.apache.org/schema/spring">
    <route>
        <from uri="direct:start"/>
        <aggregate strategyRef="aggregatorStrategy"
                   completionTimeout="3000">
            <correlationExpression>
                <simple>header.StockSymbol</simple>
            </correlationExpression>
            <to uri="mock:aggregated"/>
        </aggregate>
    </route>
</camelContext>

<bean id="aggregatorStrategy"
      class="org.apache.camel.processor.aggregate.UseLatestAggregationStrategy"/>

8.5.5. 상관 관계 표현식 지정

Java DSL에서 상관 관계 표현식은 항상 aggregate() DSL 명령에 첫 번째 인수로 전달됩니다. 여기에서 Simple Expression Language를 사용하는 것은 아닙니다. expressions 언어 또는 스크립팅 언어(예: Cryostat, XQuery, SQL 등)를 사용하여 상관 관계 표현식을 지정할 수 있습니다.

Exampe의 경우 Cryostat 표현식을 사용하여 서로 상호 작용하기 위해 다음 Java DSL 경로를 사용할 수 있습니다.

from("direct:start")
    .aggregate(xpath("/stockQuote/@symbol"), new UseLatestAggregationStrategy())
        .completionTimeout(3000)
    .to("mock:aggregated");

특정 들어오는 교환에서 상관 관계 표현식을 평가할 수 없는 경우 집계기가 기본적으로 CamelExchangeException 을 throw합니다. ignoreInvalidCorrelationKeys 옵션을 설정하여 이 예외를 비활성화할 수 있습니다. 예를 들어 Java DSL에서는 다음과 같습니다.

from(...).aggregate(...).ignoreInvalidCorrelationKeys()

XML DSL에서 ignoreInvalidCorrelationKeys 옵션은 다음과 같이 속성으로 설정할 수 있습니다.

<aggregate strategyRef="aggregatorStrategy"
           ignoreInvalidCorrelationKeys="true"
           ...>
    ...
</aggregate>

8.5.6. 집계 전략 지정

Java DSL에서는 집계 전략을 두 번째 인수로 aggregate() DSL 명령에 전달하거나 aggregationStrategy() 절을 사용하여 지정할 수 있습니다. 예를 들어 aggregationStrategy() 절을 다음과 같이 사용할 수 있습니다.

from("direct:start")
    .aggregate(header("id"))
        .aggregationStrategy(new UseLatestAggregationStrategy())
        .completionTimeout(3000)
    .to("mock:aggregated");

Apache Camel은 다음과 같은 기본 집계 전략을 제공합니다(클래스가 org.apache.camel.processor.aggregate Java 패키지에 속하는 경우).

UseLatestAggregationStrategy
지정된 상관 관계 키에 대한 마지막 교환을 반환하여 이 키와 이전 교환을 모두 삭제합니다. 예를 들어, 이 전략은 특정 주식 기호의 최신 가격을 알고 싶은 주식 교환에서 피드를 제한하는 데 유용할 수 있습니다.
UseOriginalAggregationStrategy
지정된 상관 관계 키에 대한 첫 번째 교환을 반환하여 이 키와 이후의 모든 교환을 삭제합니다. 이 전략을 사용하려면 UseOriginalAggregationStrategy.setOriginal() 를 호출하여 첫 번째 교환을 설정해야 합니다.
GroupedExchangeAggregationStrategy
지정된 상관 관계 키에 대한 모든 교환을 목록에 연결합니다. 이는 Exchange.GROUPED_EXCHANGE 교환 속성에 저장됩니다. “그룹화된 교환”을 참조하십시오.

8.5.7. 사용자 정의 집계 전략 구현

다른 집계 전략을 적용하려면 다음 집계 전략 기본 인터페이스 중 하나를 구현할 수 있습니다.

org.apache.camel.processor.aggregate.AggregationStrategy
기본 집계 전략 인터페이스입니다.
org.apache.camel.processor.aggregate.TimeoutAwareAggregationStrategy

집계 주기 시간이 초과될 때 구현에서 알림을 수신하려면 이 인터페이스를 구현합니다. 시간 초과 알림 방법에는 다음과 같은 서명이 있습니다.

void timeout(Exchange oldExchange, int index, int total, long timeout)
org.apache.camel.processor.aggregate.CompletionAwareAggregationStrategy

집계 주기가 정상적으로 완료되면 구현에서 알림을 수신하도록 하려면 이 인터페이스를 구현합니다. 알림 방법에는 다음과 같은 서명이 있습니다.

void onCompletion(Exchange exchange)

예를 들어 다음 코드는 StringAggregationStrategy 및 Cryostat AggregationStrategy: 두 가지 다른 사용자 정의 집계 전략입니다.

 //simply combines Exchange String body values using '' as a delimiter
 class StringAggregationStrategy implements AggregationStrategy {

     public Exchange aggregate(Exchange oldExchange, Exchange newExchange) {
         if (oldExchange == null) {
             return newExchange;
         }

         String oldBody = oldExchange.getIn().getBody(String.class);
         String newBody = newExchange.getIn().getBody(String.class);
         oldExchange.getIn().setBody(oldBody + "" + newBody);
         return oldExchange;
     }
 }

 //simply combines Exchange body values into an ArrayList<Object>
 class ArrayListAggregationStrategy implements AggregationStrategy {

     public Exchange aggregate(Exchange oldExchange, Exchange newExchange) {
 	    Object newBody = newExchange.getIn().getBody();
     	ArrayList<Object> list = null;
         if (oldExchange == null) {
 		    list = new ArrayList<Object>();
 		    list.add(newBody);
 		    newExchange.getIn().setBody(list);
 		    return newExchange;
         } else {
 	        list = oldExchange.getIn().getBody(ArrayList.class);
 	    	list.add(newBody);
 		    return oldExchange;
 	    }
     }
 }
참고

Apache Camel 2.0부터 AggregationStrategy.aggregate() 콜백 방법도 첫 번째 교환에 대해 호출됩니다. 집계 메서드를 처음 호출하면 oldExchange 매개 변수는 null 이고 newExchange 매개 변수에는 처음 들어오는 교환이 포함되어 있습니다.

사용자 정의 전략 클래스를 사용하여 메시지를 집계하려면 Cryostat AggregationStrategy 에서는 다음과 같은 경로를 정의합니다.

from("direct:start")
    .aggregate(header("StockSymbol"), new ArrayListAggregationStrategy())
    .completionTimeout(3000)
    .to("mock:result");

다음과 같이 XML에서 사용자 정의 집계 전략을 사용하여 경로를 구성할 수도 있습니다.

<camelContext xmlns="http://camel.apache.org/schema/spring">
  <route>
    <from uri="direct:start"/>
    <aggregate strategyRef="aggregatorStrategy"
               completionTimeout="3000">
      <correlationExpression>
        <simple>header.StockSymbol</simple>
      </correlationExpression>
      <to uri="mock:aggregated"/>
    </aggregate>
  </route>
</camelContext>

<bean id="aggregatorStrategy" class="com.my_package_name.ArrayListAggregationStrategy"/>

8.5.8. 사용자 정의 집계 전략의 라이프사이클 제어

라이프사이클이 이를 제어하는 엔터프라이즈 통합 패턴의 라이프사이클과 일치하도록 사용자 정의 집계 전략을 구현할 수 있습니다. 이는 집계 전략이 정상적으로 종료될 수 있는지 확인하는 데 유용할 수 있습니다.

라이프사이클 지원을 통해 집계 전략을 구현하려면 org.apache.camel.Service 인터페이스( AggregationStrategy 인터페이스 외에도)를 구현하고 start()stop() 라이프사이클 메서드 구현을 제공해야 합니다. 예를 들어 다음 코드 예제에서는 라이프사이클 지원이 포함된 집계 전략에 대한 개요를 보여줍니다.

// Java
import org.apache.camel.processor.aggregate.AggregationStrategy;
import org.apache.camel.Service;
import java.lang.Exception;
...
class MyAggStrategyWithLifecycleControl
       implements AggregationStrategy, Service {

    public Exchange aggregate(Exchange oldExchange, Exchange newExchange) {
        // Implementation not shown...
        ...
    }

    public void start() throws Exception {
        // Actions to perform when the enclosing EIP starts up
        ...
    }

    public void stop() throws Exception {
        // Actions to perform when the enclosing EIP is stopping
        ...
    }
}

8.5.9. 속성 교환

다음 속성은 집계된 각 교환에 대해 설정됩니다.

헤더유형집계된 교환 속성 설명

Exchange.AGGREGATED_SIZE

int

이 교환에 포함된 총 거래 거래 수입니다.

Exchange.AGGREGATED_COMPLETED_BY

문자열

집계 교환을 완료하는 메커니즘을 나타냅니다. 가능한 값은 서술자,크기,시간 초과,간격 또는 소비자 입니다.

다음 속성은 SQL 구성 요소 집계 리포지터리에 의해 재전송되는 교환에 설정되어 있습니다( “영구 집계 리포지토리”참조).

헤더유형Redelivered Exchange Properties 설명

Exchange.REDELIVERY_COUNTER

int

현재 재전송 시도의 시퀀스 번호( 1에서 시작)입니다.

8.5.10. 완료 조건 지정

집계 교환이 수집기를 떠나 경로의 다음 노드로 진행하는 시기를 결정하는 완료 조건을 하나 이상 지정해야 합니다. 다음 완료 조건을 지정할 수 있습니다.

completionPredicate
각 교환이 집계된 후 서술자를 평가하여 완전성을 결정합니다. true 값은 집계 교환이 완료되었음을 나타냅니다. 또는 이 옵션을 설정하는 대신 Predicate 인터페이스를 구현하는 사용자 정의 AggregationStrategy 를 정의할 수 있습니다. 이 경우 AggregationStrategy 가 completion 서술자로 사용됩니다.
completionSize
지정된 수의 교환이 집계된 후 집계 교환을 완료합니다.
completionTimeout

( completionInterval과 호환되지 않음) 지정된 타임아웃 내에 들어오는 교환이 집계되지 않는 경우 집계 교환을 완료합니다.

즉, 타임아웃 메커니즘은 상관 관계 키 값에 대한 타임아웃을 추적합니다. 클록은 특정 키 값을 사용한 최신 교환이 수신된 후 진드기가 시작됩니다. 동일한 키 값을 가진 다른 교환이 지정된 시간 내에 수신 되지 않으면 해당 집계 교환이 완료로 표시되고 경로의 다음 노드로 전송됩니다.

completionInterval

( completionTimeout과 호환되지 않음) 각 시간 간격 (특정 길이)이 경과한 후 모든 미결한 집계 교환을 완료합니다.

시간 간격은 각 집계 교환에 맞게 조정 되지 않습니다. 이 메커니즘은 모든 미결 집계 교환을 동시에 완료하도록 합니다. 따라서 경우에 따라 이 메커니즘은 집계를 시작한 직후 집계 교환을 완료할 수 있습니다.

completionFromBatchConsumer
배치 소비자 메커니즘을 지원하는 소비자 끝점과 함께 사용되는 경우, 이 완료 옵션은 소비자 끝점에서 수신하는 정보를 기반으로 현재 교환 처리가 완료된 시기를 자동으로 파악합니다. “배치 소비자”을 참조하십시오.
forceCompletionOnStop
이 옵션을 사용하면 현재 경로 컨텍스트가 중지될 때 모든 미결 집계 교환이 강제 완료됩니다.

이전 완료 조건은 동시에 활성화할 수 없는 completionTimeoutcompletionInterval 조건을 제외하고 임의로 결합할 수 있습니다. 조건이 함께 사용되는 경우 일반적인 규칙은 트리거하는 첫 번째 완료 조건이 효과적인 완료 조건이라는 것입니다.

8.5.11. 완료 서술자 지정

집계된 교환이 완료된 시기를 결정하는 임의의 서술자 표현식을 지정할 수 있습니다. 서술자 표현식을 평가하는 방법은 다음 두 가지가 있습니다.

  • 최신 집계 교환에서 기본 동작입니다.
  • 가장 최근에 들어오는 교환 Cryostat-침반 동작에서는 eagerCheckCompletion 옵션을 활성화할 때 이 동작이 선택됩니다.

예를 들어 ALERT 메시지를 받을 때마다 주식 따옴표의 스트림을 종료하려는 경우(최신 들어오는 교환에서 MsgType 헤더 값으로 표시됨) 다음과 같은 경로를 정의할 수 있습니다.

from("direct:start")
    .aggregate(
      header("id"),
      new UseLatestAggregationStrategy()
    )
        .completionPredicate(
          header("MsgType").isEqualTo("ALERT")
         )
        .eagerCheckCompletion()
    .to("mock:result");

다음 예제에서는 XML을 사용하여 동일한 경로를 구성하는 방법을 보여줍니다.

<camelContext xmlns="http://camel.apache.org/schema/spring">
  <route>
    <from uri="direct:start"/>
    <aggregate strategyRef="aggregatorStrategy"
               eagerCheckCompletion="true">
      <correlationExpression>
          <simple>header.StockSymbol</simple>
      </correlationExpression>
      <completionPredicate>
          <simple>$MsgType = 'ALERT'</simple>
      </completionPredicate>
      <to uri="mock:result"/>
    </aggregate>
  </route>
</camelContext>

<bean id="aggregatorStrategy"
      class="org.apache.camel.processor.aggregate.UseLatestAggregationStrategy"/>

8.5.12. 동적 완료 시간 지정

들어오는 모든 교환에 대해 시간 초과 값이 다시 계산되는 동적 완료 시간 초과를 지정할 수 있습니다. 예를 들어 들어오는 각 교환에서 시간 초과 값을 설정하려면 다음과 같이 경로를 정의할 수 있습니다.

from("direct:start")
    .aggregate(header("StockSymbol"), new UseLatestAggregationStrategy())
        .completionTimeout(header("timeout"))
    .to("mock:aggregated");

다음과 같이 XML DSL에서 동일한 경로를 구성할 수 있습니다.

<camelContext xmlns="http://camel.apache.org/schema/spring">
    <route>
        <from uri="direct:start"/>
        <aggregate strategyRef="aggregatorStrategy">
            <correlationExpression>
                <simple>header.StockSymbol</simple>
            </correlationExpression>
            <completionTimeout>
                <header>timeout</header>
            </completionTimeout>
            <to uri="mock:aggregated"/>
        </aggregate>
    </route>
</camelContext>

<bean id="aggregatorStrategy"
      class="org.apache.camel.processor.UseLatestAggregationStrategy"/>
참고

동적 값이 null 또는 0 인 경우 Apache Camel이 이 값을 사용하도록 고정 시간 초과 값을 추가할 수도 있습니다.

8.5.13. 동적 완료 크기 지정

들어오는 모든 교환에 대해 완료 크기가 다시 계산되는 동적 완료 크기를 지정할 수 있습니다. 예를 들어 들어오는 각 교환에서 mySize 헤더에서 완료 크기를 설정하려면 다음과 같이 경로를 정의할 수 있습니다.

from("direct:start")
    .aggregate(header("StockSymbol"), new UseLatestAggregationStrategy())
        .completionSize(header("mySize"))
    .to("mock:aggregated");

Spring XML을 사용하는 것과 동일한 예:

<camelContext xmlns="http://camel.apache.org/schema/spring">
    <route>
        <from uri="direct:start"/>
        <aggregate strategyRef="aggregatorStrategy">
            <correlationExpression>
                <simple>header.StockSymbol</simple>
            </correlationExpression>
            <completionSize>
                <header>mySize</header>
            </completionSize>
            <to uri="mock:aggregated"/>
        </aggregate>
    </route>
</camelContext>

<bean id="aggregatorStrategy"
      class="org.apache.camel.processor.UseLatestAggregationStrategy"/>
참고

동적 값이 null 또는 0 인 경우 Apache Camel이 이 값을 사용하도록 고정 크기 값을 추가할 수도 있습니다.

8.5.14. AggregationStrategy 내에서 단일 그룹 강제 완료

사용자 정의 집계Strategy 클래스를 구현하는 경우 AggregationStrategy. aggregate() 메서드에서 반환된 교환 시 Exchange.AGGREGATION_COMPLETE_CURRENT_GROUP 교환 속성을 true 로 설정하여 현재 메시지 그룹을 강제로 완료할 수 있는 메커니즘이 있습니다. 이 메커니즘은 현재 그룹에 영향을 미칩니다. 다른 메시지 그룹(다른 상관관계 ID 포함)은 완료 하지 않습니다. 이 메커니즘은 서술자, 크기, 시간 초과 등과 같은 기타 완료 메커니즘을 재정의합니다.

예를 들어 다음 샘플 AggregationStrategy 클래스는 메시지 본문 크기가 5보다 큰 경우 현재 그룹을 완료합니다.

// Java
public final class MyCompletionStrategy implements AggregationStrategy {
    @Override
    public Exchange aggregate(Exchange oldExchange, Exchange newExchange) {
        if (oldExchange == null) {
            return newExchange;
        }
        String body = oldExchange.getIn().getBody(String.class) + "+"
            + newExchange.getIn().getBody(String.class);
        oldExchange.getIn().setBody(body);
        if (body.length() >= 5) {
            oldExchange.setProperty(Exchange.AGGREGATION_COMPLETE_CURRENT_GROUP, true);
        }
        return oldExchange;
    }
}

8.5.15. 특수 메시지로 모든 그룹 강제 완료

특수 헤더가 있는 메시지를 경로로 전송하여 모든 미해결 집계 메시지를 강제로 완료할 수 있습니다. 강제 완료에 사용할 수 있는 두 가지 대체 헤더 설정이 있습니다.

Exchange.AGGREGATION_COMPLETE_ALL_GROUPS
현재 집계 주기를 강제 완료하려면 true 로 설정합니다. 이 메시지는 순전히 신호 역할을 하며 집계 주기에 포함되지 않습니다. 이 신호 메시지를 처리하면 메시지의 콘텐츠가 삭제됩니다.
Exchange.AGGREGATION_COMPLETE_ALL_GROUPS_INCLUSIVE
현재 집계 주기를 강제 완료하려면 true 로 설정합니다. 이 메시지는 현재 집계 주기에 포함됩니다.

8.5.16. AggregateController 사용

org.apache.camel.processor.aggregate.AggregateController 를 사용하면 Java 또는 Cryostat API를 사용하여 런타임 시 집계를 제어할 수 있습니다. 이는 교환 그룹을 강제 수행하거나 현재 런타임 통계를 쿼리하는 데 사용할 수 있습니다.

사용자 지정이 구성되지 않은 경우 집계기는 getAggregateController() 메서드를 사용하여 액세스할 수 있는 기본 구현을 제공합니다. 그러나 aggregateController를 사용하여 경로에서 컨트롤러를 쉽게 구성할 수 있습니다.

private AggregateController controller = new DefaultAggregateController();

from("direct:start")
   .aggregate(header("id"), new MyAggregationStrategy()).completionSize(10).id("myAggregator")
      .aggregateController(controller)
      .to("mock:aggregated");

또한 AggregateController에서 API를 사용하여 강제로 완료할 수 있습니다. 예를 들어, foo 키가 있는 그룹을 완료하려면 다음을 수행합니다.

int groups = controller.forceCompletionOfGroup("foo");

반환되는 수는 완료된 그룹 수입니다. 다음은 모든 그룹을 완료하는 API입니다.

 int groups = controller.forceCompletionOfAllGroups();

8.5.17. 고유한 상관 관계 키 강제 적용

일부 집계 시나리오에서는 상관 관계 키가 교환 배치마다 고유한 조건을 적용해야 할 수 있습니다. 즉, 특정 상관 키의 집계 교환이 완료되면 해당 상관 키와의 집계 교환이 더 이상 진행되지 않도록 해야 합니다. 예를 들어 경로의 후자 부분이 고유한 상관관계 키 값으로 교환을 처리할 것으로 예상되는 경우 이 조건을 시행할 수 있습니다.

완료 조건을 구성하는 방법에 따라 특정 상관 관계를 사용하여 여러 집계 교환이 생성될 위험이 있을 수 있습니다. 예를 들어 특정 상관 키와의 모든 교환이 수신될 때까지 대기하도록 설계된 완료 서술자를 정의할 수 있지만 해당 키로의 모든 교환이 도달하기 전에 실행될 수 있는 완료 시간 초과를 정의할 수도 있습니다. 이 경우 늦은 교환으로 인해 동일한 상관 관계 키 값을 사용하여 두 번째 집계 교환이 발생할 수 있습니다.

이러한 시나리오의 경우 closeCorrelationKeyOnCompletion 옵션을 설정하여 이전 상관 키 값을 복제하는 집계 교환을 억제하도록 집계기를 구성할 수 있습니다. 중복된 상관관계 키 값을 억제하려면 집계자가 캐시에 이전 상관관계 키 값을 기록해야 합니다. 이 캐시의 크기(캐시된 상관 키 수)는 closeCorrelationKeyOnCompletion() DSL 명령에 대한 인수로 지정됩니다. 무제한 크기의 캐시를 지정하려면 0 또는 음수 정수 값을 전달할 수 있습니다. 예를 들어 캐시 크기를 10000 키 값으로 지정하려면 다음을 수행합니다.

from("direct:start")
    .aggregate(header("UniqueBatchID"), new MyConcatenateStrategy())
        .completionSize(header("mySize"))
        .closeCorrelationKeyOnCompletion(10000)
    .to("mock:aggregated");

집계 교환이 중복된 상관관계 키 값으로 완료되면 수집기에서 ClosedCorrelationKeyException 예외를 throw합니다.

8.5.18. 단순 표현식을 사용한 스트림 기반 처리

스트리밍 모드에서 tokenize XML 하위 명령을 사용하여 간단한 언어 표현식을 토큰으로 사용할 수 있습니다. 간단한 언어 표현식을 사용하면 동적 토큰을 지원할 수 있습니다.

예를 들어 Java를 사용하여 태그 사람이 구분하는 일련의 이름을 분할하기 위해 tokenize XML files 및 Simple 언어 토큰을 사용하여 파일을 name 요소로 분할할 수 있습니다.

public void testTokenizeXMLPairSimple() throws Exception {
        Expression exp = TokenizeLanguage.tokenizeXML("${header.foo}", null);

< person>로 구분되는 이름의 입력 문자열을 가져오고 토큰으로 < person >를 설정합니다.

        exchange.getIn().setHeader("foo", "<person>");
        exchange.getIn().setBody("<persons><person>James</person><person>Claus</person><person>Jonathan</person><person>Hadrian</person></persons>");

입력에서 분리된 이름을 나열합니다.

        List<?> names = exp.evaluate(exchange, List.class);
        assertEquals(4, names.size());

        assertEquals("<person>James</person>", names.get(0));
        assertEquals("<person>Claus</person>", names.get(1));
        assertEquals("<person>Jonathan</person>", names.get(2));
        assertEquals("<person>Hadrian</person>", names.get(3));
    }

8.5.19. 그룹화된 교환

발신 배치에서 집계된 모든 교환을 단일 org.apache.camel.impl.GroupedExchange 홀더 클래스로 결합할 수 있습니다. 그룹화된 교환을 활성화하려면 다음 Java DSL 경로에 표시된 것처럼 group exchanges() 옵션을 지정합니다.

from("direct:start")
    .aggregate(header("StockSymbol"))
        .completionTimeout(3000)
        .groupExchanges()
    .to("mock:result");

mock:result 로 전송된 그룹화된 교환에는 메시지 본문에 집계된 교환 목록이 포함되어 있습니다. 다음 코드 줄은 후속 프로세서가 목록 형태로 그룹화된 교환의 콘텐츠에 액세스하는 방법을 보여줍니다.

// Java
List<Exchange> grouped = ex.getIn().getBody(List.class);
참고

그룹화된 교환 기능을 활성화하면 집계 전략을 구성 해서는 안 됩니다(그룹화된 교환 기능은 집계 전략 자체임).

참고

발신 교환의 자산에서 그룹화된 교환에 액세스하는 오래된 접근 방식은 더 이상 사용되지 않으며 향후 릴리스에서 제거됩니다.

8.5.20. 배치 소비자

집계기를 배치 소비자 패턴과 함께 작동하여 배치 소비자가 보고한 총 메시지 수를 집계할 수 있습니다(배치 소비자 엔드포인트는 들어오는 교환에 CamelBatchSize,CamelBatchIndex , CamelBatchComplete 속성 설정). 예를 들어 File 소비자 엔드포인트에서 찾은 모든 파일을 집계하려면 다음과 같은 경로를 사용할 수 있습니다.

from("file://inbox")
    .aggregate(xpath("//order/@customerId"), new AggregateCustomerOrderStrategy())
    .completionFromBatchConsumer()
    .to("bean:processOrder");

현재 다음 엔드포인트는 파일, FTP, 메일, iBatis 및 JPA와 같은 배치 소비자 메커니즘을 지원합니다.

8.5.21. 영구 집계 리포지토리

기본 집계자는 메모리 내 전용 AggregationRepository 를 사용합니다. 보류 중인 집계된 리테일링을 영구적으로 저장하려면 SQL 구성 요소를 영구 집계 리포지토리로 사용할 수 있습니다. SQL 구성 요소에는 집계된 메시지를 on-the-fly로 유지하고 메시지를 손실하지 않는 JdbcAggregationRepository 가 포함되어 있습니다.

교환이 성공적으로 처리되면 리포지토리에서 확인 메서드를 호출할 때 완료로 표시됩니다. 즉, 동일한 교환이 다시 실패하면 성공할 때까지 다시 시도됩니다.

camel-sql에 대한 종속성 추가

SQL 구성 요소를 사용하려면 프로젝트에 camel-sql 에 대한 종속성을 포함해야 합니다. 예를 들어 Maven pom.xml 파일을 사용하는 경우:

<dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-sql</artifactId>
    <version>x.x.x</version>
    <!-- use the same version as your Camel core version -->
</dependency>

집계 데이터베이스 테이블 생성

지속성을 위해 별도의 집계 및 완료된 데이터베이스 테이블을 생성해야 합니다. 예를 들어 다음 쿼리는 my_aggregation_repo 라는 데이터베이스에 대한 테이블을 생성합니다.

CREATE TABLE my_aggregation_repo (
 id varchar(255) NOT NULL,
 exchange blob NOT NULL,
 constraint aggregation_pk PRIMARY KEY (id)
);

CREATE TABLE my_aggregation_repo_completed (
 id varchar(255) NOT NULL,
 exchange blob NOT NULL,
 constraint aggregation_completed_pk PRIMARY KEY (id)
);
}

집계 리포지토리 구성

프레임워크 XML 파일에서 집계 리포지토리를 구성해야 합니다(예: Spring 또는 블루프린트).

<bean id="my_repo"
    class="org.apache.camel.processor.aggregate.jdbc.JdbcAggregationRepository">
    <property name="repositoryName" value="my_aggregation_repo"/>
    <property name="transactionManager" ref="my_tx_manager"/>
    <property name="dataSource" ref="my_data_source"/>
    ...
</bean>

repositoryName,transactionManagerdataSource 속성이 필요합니다. 영구 집계 리포지토리에 대한 자세한 내용은 Apache Camel 구성 요소 참조 가이드의 SQL 구성 요소를 참조하십시오.

8.5.22. 스레드 옵션

그림 8.6. “수집기 구현” 에 표시된 대로 집계기는 경로의 후자 부분과 분리되며, 경로의 후자 부분으로 전송된 교환은 전용 스레드 풀에 의해 처리됩니다. 기본적으로 이 풀에는 단일 스레드만 포함됩니다. 여러 스레드가 있는 풀을 지정하려면 다음과 같이 parallelProcessing 옵션을 활성화합니다.

from("direct:start")
    .aggregate(header("id"), new UseLatestAggregationStrategy())
        .completionTimeout(3000)
        .parallelProcessing()
    .to("mock:aggregated");

기본적으로 10개의 작업자 스레드가 있는 풀이 생성됩니다.

생성된 스레드 풀을 더 많이 제어하려면 executorService 옵션을 사용하여 사용자 지정 java.util.concurrent.ExecutorService 인스턴스를 지정합니다(이 경우 병렬Processing 옵션을 활성화할 필요가 없음).

8.5.23. 목록에 집계

일반적인 집계 시나리오에서는 일련의 들어오는 메시지 본문을 List 오브젝트에 집계해야 합니다. 이 시나리오를 용이하게 하기 위해 Apache Camel은 AbstractListAggregationStrategy 추상 클래스를 제공합니다. 이 클래스를 빠르게 확장하여 이 사례에 대한 집계 전략을 생성할 수 있습니다. 유형 T 의 들어오는 메시지 본문은 List<T> 유형의 메시지 본문을 사용하여 완료된 교환으로 집계됩니다.

예를 들어 일련의 Integer 메시지 본문을 List <Integer> 오브젝트에 집계하려면 다음과 같이 정의된 집계 전략을 사용할 수 있습니다.

import org.apache.camel.processor.aggregate.AbstractListAggregationStrategy;
...
/**
 * Strategy to aggregate integers into a List<Integer>.
 */
public final class MyListOfNumbersStrategy extends AbstractListAggregationStrategy<Integer> {
 
    @Override
    public Integer getValue(Exchange exchange) {
        // the message body contains a number, so just return that as-is
        return exchange.getIn().getBody(Integer.class);
    }
}

8.5.24. 수집기 옵션

수집기는 다음 옵션을 지원합니다.

표 8.1. 수집기 옵션

옵션Default설명

correlationExpression

 

집계에 사용할 상관관계 키를 평가하는 필수 표현식입니다. 동일한 상관관계 키가 있는 교환은 함께 집계됩니다. correlation 키를 평가할 수 없는 경우 예외가 발생합니다. ignoreBadCorrelationKeys 옵션을 사용하여 이를 비활성화할 수 있습니다.

aggregationStrategy

 

들어오는 교환을 이미 병합한 교환과 병합 하는 데 사용되는 필수 집계Strategy 입니다. 처음 호출 시 oldExchange 매개변수는 null 입니다. 이후 호출 시 oldExchange 에는 병합된 교환이 포함되어 있으며 newExchange 는 물론 새로운 들어오는 교환입니다. Camel 2.9.2 이후의 전략은 선택 옵션으로 시간 초과 콜백을 지원하는 TimeoutAwareAggregationStrategy 구현일 수 있습니다. Camel 2.16 이후부터 이 전략은 PreCompletionAwareAggregationStrategy 구현일 수도 있습니다. 사전 완료 모드에서 완료 검사를 실행합니다.

strategyRef

 

레지스트리에서 집계Strategy 를 조회하는 참조입니다.

completionSize

 

집계가 완료되기 전에 집계된 메시지 수입니다. 이 옵션은 고정 값으로 설정하거나 동적으로 크기를 평가할 수 있는 Expression을 사용하여 설정할 수 있으며 결과적으로 Integer 를 사용합니다. If both are set Camel will fallback to use the fixed value if the expression result was null or 0.

completionTimeout

 

집계된 교환이 완료되기 전에 비활성화되어야 하는 시간(밀리초)입니다. 이 옵션을 고정 값으로 설정하거나 시간 초과를 동적으로 평가할 수 있는 Expression을 사용하면 으로 사용할 수 있습니다. If both are set Camel will fallback to use the fixed value if the expression result was null or 0. completionInterval과 함께 이 옵션을 사용할 수 없으며 둘 중 하나만 사용할 수 있습니다.

completionInterval

 

집계자가 현재 집계된 모든 교환을 완료하는 밀리 초 단위의 반복 기간입니다. Camel에는 매번 트리거되는 백그라운드 작업이 있습니다. completionTimeout과 함께 이 옵션을 사용할 수 없으며 그 중 하나만 사용할 수 있습니다.

completionPredicate

 

집계된 교환이 완료되면 신호인 org.apache.camel.Predicate 유형의 서술자를 지정합니다. 또는 이 옵션을 설정하는 대신 Predicate 인터페이스를 구현하는 사용자 정의 AggregationStrategy 를 정의할 수 있습니다. 이 경우 AggregationStrategy 가 completion 서술자로 사용됩니다.

completionFromBatchConsumer

false

이 옵션은 교환이 배치 소비자에서 오는 경우입니다. 그런 다음 8.5절. “수집기” 는 메시지 헤더 CamelBatchSize 에서 Batch Consumer에 의해 결정된 배치 크기를 사용합니다. 자세한 내용은 Batch Consumer를 참조하십시오. 이는 지정된 폴링에서 사용되는 모든 파일을 참조하는 파일 끝점에서 집계하는 데 사용할 수 있습니다.

eagerCheckCompletion

false

새로 들어오는 교환이 수신될 때 완료를 신속하게 점검할지 여부입니다. 이 옵션은 그에 따라 변경 사항이 전달될 때 completionPredicate 옵션의 동작에 영향을 미칩니다. Predicate에서 전달된 교환이 집계된 교환인 경우, AggregationStrategy 에서 집계된 교환에 저장할 수 있는 모든 정보를 서술자에 사용할 수 있습니다. Predicate에서 전달된 교환이 true 인 경우 들어오는 교환이 됩니다. 즉, 들어오는 교환에서 데이터에 액세스할 수 있습니다.

forceCompletionOnStop

false

true 인 경우 현재 경로 컨텍스트가 중지되면 집계된 모든 교환을 완료합니다.

groupExchanges

false

활성화된 경우 Camel은 집계된 모든 교환을 집계된 모든 교환을 하나의 결합된 org.apache.camel.impl.GroupedExchange 홀더 클래스로 그룹화합니다. 결과적으로 수집기에서 하나의 교환만 전송됩니다. 사용자 지정 집계Strategy 를 코딩하지 않고 들어오는 많은 교환을 단일 출력 교환으로 결합하는 데 사용할 수 있습니다.

ignoreInvalidCorrelationKeys

false

값으로 평가할 수 없는 상관관계 키를 무시할지 여부입니다. 기본적으로 Camel은 예외를 발생하지만 이 옵션을 활성화하고 대신 이 상황을 무시할 수 있습니다.

closeCorrelationKeyOnCompletion

 

늦은 교환을 수락하거나 허용하지 않는지 여부입니다. 이를 통해 상관관계 키가 이미 완료된 경우 동일한 상관 관계 키를 가진 새로운 교환이 거부됨을 나타낼 수 있습니다. 그런 다음 Camel은 closedCorrelationKeyException 예외를 throw합니다. 이 옵션을 사용할 때 마지막 X의 닫힌 상관 키 수를 유지하는 LRUCache의 숫자인 정수 를 전달합니다. 0 또는 음수 값을 전달하여 바인딩되지 않은 캐시를 표시할 수 있습니다. 숫자를 전달하면 서로 다른 상관 키의 로그를 사용하는 경우 캐시가 너무 커지지 않도록 합니다.

discardOnCompletionTimeout

false

Camel 2.5: 시간 초과로 인해 완료되는 교환이 취소되어야 하는지의 여부입니다. 활성화하면 시간 초과가 발생하면 집계된 메시지가 전송 되지 않고 삭제되지 않습니다 (거부됨).

aggregationRepository

 

org.apache.camel.spi.AggregationRepository 의 자체 구현을 연결하여 현재 진행 중인 집계 교환을 추적할 수 있습니다. Camel은 기본적으로 메모리 기반 구현을 사용합니다.

aggregationRepositoryRef

 

레지스트리에서 aggregationRepository 조회에 대한 참조입니다.

parallelProcessing

false

집계가 완료되면 수집기에서 전송됩니다. 이 옵션은 Camel에서 동시성에 여러 스레드가 있는 스레드 풀을 사용해야 하는지 여부를 나타냅니다. 사용자 지정 스레드 풀이 지정되지 않은 경우 Camel은 10개의 동시 스레드가 있는 기본 풀을 생성합니다.

executorService

 

parallelProcessing 을 사용하는 경우 사용할 사용자 지정 스레드 풀을 지정할 수 있습니다. 실제로 병렬Processing 이 사용자 정의 스레드 풀을 사용하지 않는 경우에도 집계된 교환을 보내는 데도 사용됩니다.

executorServiceRef

 

레지스트리에서 executorService 조회에 대한 참조

timeoutCheckerExecutorService

 

completionTimeout , completionTimeout Expression 또는 completionInterval 옵션 중 하나를 사용하는 경우 백그라운드 스레드가 생성되어 모든 수집기가 완료되었는지 확인합니다. 모든 수집기에 대해 새 스레드를 생성하는 대신 사용할 사용자 지정 스레드 풀을 제공하려면 이 옵션을 설정합니다.

timeoutCheckerExecutorServiceRef

 

레지스트리에서 timeoutCheckerExecutorService 를 조회하는 데 대한 참조입니다.

completeAllOnStop

 

Aggregator를 중지하면 이 옵션을 사용하면 집계 리포지토리에서 보류 중인 모든 리스터를 완료할 수 있습니다.

optimisticLocking

false

집계 리포지토리와 함께 사용할 수 있는 최적의 잠금을 설정합니다.

optimisticLockRetryPolicy

 

최적화 잠금에 대한 재시도 정책을 구성합니다.

8.6. Resequencer

8.6.1. 개요

그림 8.7. “Resequencer 패턴” 에 표시된 resequencer 패턴을 사용하면 sequencing 표현식에 따라 메시지를 다시 시작할 수 있습니다. sequencing 식에 대한 낮은 값을 생성하는 메시지는 높은 값을 생성하는 일괄 처리 및 메시지 앞으로 이동됩니다.

그림 8.7. Resequencer 패턴

Resequencer 패턴

Apache Camel은 다음 두 가지 resequencing 알고리즘을 지원합니다.

  • 일괄 처리 resequencing ECDHE - 메시지를 일괄 처리로 수집, 메시지를 정렬하고 출력으로 보냅니다.
  • 메시지 간 격차 감지 를 기반으로 메시지 스트림을 재시동(continuous)하는 스트림 입니다.

기본적으로 resequencer는 중복 메시지를 지원하지 않으며 메시지가 동일한 메시지 표현식으로 도달하는 경우 마지막 메시지만 유지합니다. 그러나 배치 모드에서는 resequencer를 활성화하여 중복을 허용할 수 있습니다.

8.6.2. 일괄 재쿼싱

배치 resequencing 알고리즘은 기본적으로 활성화되어 있습니다. 예를 들어 TimeStamp 헤더에 포함된 타임스탬프의 값에 따라 들어오는 메시지 배치를 다시 얻으려면 Java DSL에서 다음 경로를 정의할 수 있습니다.

from("direct:start").resequence(header("TimeStamp")).to("mock:result");

기본적으로 일괄 처리는 최대 100개의 메시지(기본 일괄 처리 크기)까지 1000밀리초(기본 배치 시간 초과)의 시간 간격에 도달하는 들어오는 모든 메시지를 수집하여 가져옵니다. BatchResequencerConfig 인스턴스를 유일한 인수로 사용하는 batch() DSL 명령을 추가하여 배치 제한 시간 및 배치 크기의 값을 사용자 지정할 수 있습니다. 예를 들어, 배치가 4000밀리 초의 시간 창에서 수집된 메시지로 구성되도록 이전 경로를 수정하려면 최대 300개의 메시지까지 다음과 같이 Java DSL 경로를 정의할 수 있습니다.

import org.apache.camel.model.config.BatchResequencerConfig;

RouteBuilder builder = new RouteBuilder() {
    public void configure() {
        from("direct:start").resequence(header("TimeStamp")).batch(new BatchResequencerConfig(300,4000L)).to("mock:result");
    }
};

XML 구성을 사용하여 배치 resequencer 패턴을 지정할 수도 있습니다. 다음 예제에서는 배치 크기가 300이고 일괄 시간 초과는 4000밀리초인 배치 resequencer를 정의합니다.

<camelContext id="resequencerBatch" xmlns="http://camel.apache.org/schema/spring">
  <route>
    <from uri="direct:start" />
    <resequence>
      <!--
        batch-config can be omitted for default (batch) resequencer settings
      -->
      <batch-config batchSize="300" batchTimeout="4000" />
      <simple>header.TimeStamp</simple>
      <to uri="mock:result" />
    </resequence>
  </route>
</camelContext>

8.6.3. 배치 옵션

표 8.2. “일괄 복원기 옵션” 배치 모드에서만 사용할 수 있는 옵션을 표시합니다.

표 8.2. 일괄 복원기 옵션

Java DSLXML DSLDefault설명

allowDuplicates()

batch-config/@allowDuplicates

false

true 인 경우 일괄 처리에서 중복된 메시지를 삭제하지 마십시오. 즉, 중복 된 메시지는 메시지 표현식이 동일한 값으로 평가됨을 의미합니다.

reverse()

batch-config/@reverse

false

true 인 경우 메시지를 역순으로 둡니다(메시지 표현식에 적용되는 기본 순서는 String.compareTo()에서 정의된 대로 Java 문자열 사전 순서를 기반으로 합니다).

예를 들어 JMSPriority 를 기반으로 JMS 대기열에서 메시지를 분리하려면 다음과 같이 옵션 allowDuplicatesreverse 를 결합해야 합니다.

from("jms:queue:foo")
        // sort by JMSPriority by allowing duplicates (message can have same JMSPriority)
        // and use reverse ordering so 9 is first output (most important), and 0 is last
        // use batch mode and fire every 3th second
        .resequence(header("JMSPriority")).batch().timeout(3000).allowDuplicates().reverse()
        .to("mock:result");

8.6.4. 스트림 resequencing

스트림 resequencing 알고리즘을 활성화하려면 stream()resequence() DSL 명령에 추가해야 합니다. 예를 들어 seqnum 헤더의 시퀀스 번호 값을 기반으로 들어오는 메시지를 다시 만들려면 다음과 같이 DSL 경로를 정의합니다.

from("direct:start").resequence(header("seqnum")).stream().to("mock:result");

스트림 처리 resequencer 알고리즘은 고정된 배치 크기가 아닌 메시지 스트림의 격차 감지를 기반으로 합니다. 시간 초과와 함께 갭 탐지는 시퀀스의 메시지 수(즉, 배치 크기)를 미리 알아야 하는 제약 조건을 제거합니다. 메시지에는 고유한 시퀀스 번호가 포함되어야 하며 이 시퀀스 번호는 다음과 같이 알려져 있어야 합니다. 예를 들어, 시퀀스 번호 3 이 있는 메시지는 시퀀스 번호 2 와 시퀀스 번호 4 가 있는 연속 메시지인 메시지입니다. 메시지 시퀀스 2,3,53 의 후속 작업이 누락되었기 때문에 차이가 있습니다. 따라서 resequencer는 메시지 4 가 도착하거나 시간 초과가 발생할 때까지 메시지 5 를 유지해야 합니다.

기본적으로 스트림 resequencer는 시간 초과 1000밀리초와 최대 메시지 용량 100으로 구성됩니다. 스트림의 시간 제한 및 메시지 용량을 사용자 지정하려면 StreamResequencerConfig 오브젝트를 stream() 에 대한 인수로 전달할 수 있습니다. 예를 들어 메시지 용량이 5000이고 시간 초과를 4000밀리초로 스트림 재시저를 구성하려면 다음과 같이 경로를 정의합니다.

// Java
import org.apache.camel.model.config.StreamResequencerConfig;

RouteBuilder builder = new RouteBuilder() {
    public void configure() {
        from("direct:start").resequence(header("seqnum")).
            stream(new StreamResequencerConfig(5000, 4000L)).
            to("mock:result");
    }
};

메시지 스트림에서 연속 메시지(즉, 인접한 시퀀스 번호가 있는 메시지) 간의 최대 시간 지연이 알려지면 resequencer의 timeout 매개변수를 이 값으로 설정해야 합니다. 이 경우 스트림의 모든 메시지가 올바른 순서로 다음 프로세서로 전달되도록 보장할 수 있습니다. out-of-sequence 시간 차이에 비해 시간 초과 값이 낮을수록 resequencer가 시퀀스에서 메시지를 전달할 가능성이 높습니다. 용량 매개변수가 충분히 높은 용량 값에 의해 대규모 시간 초과 값을 지원해야 합니다. 여기서 resequencer가 메모리가 부족하지 않도록 합니다.

long 이외의 일부 유형의 시퀀스 번호를 사용하려면 다음과 같이 사용자 지정 비교기를 정의해야 합니다.

// Java
ExpressionResultComparator<Exchange> comparator = new MyComparator();
StreamResequencerConfig config = new StreamResequencerConfig(5000, 4000L, comparator);
from("direct:start").resequence(header("seqnum")).stream(config).to("mock:result");

XML 구성을 사용하여 스트림 resequencer 패턴을 지정할 수도 있습니다. 다음 예제에서는 메시지 용량이 5000이고 시간 초과가 4000밀리초인 스트림 resequencer를 정의합니다.

<camelContext id="resequencerStream" xmlns="http://camel.apache.org/schema/spring">
  <route>
    <from uri="direct:start"/>
    <resequence>
      <stream-config capacity="5000" timeout="4000"/>
      <simple>header.seqnum</simple>
      <to uri="mock:result" />
    </resequence>
  </route>
</camelContext>

8.6.5. 잘못된 교환 무시

resequencer EIP는 들어오는 교환이 유효하지 않은 경우, 어떤 이유로든 sequencing 표현식을 평가할 수 없는 경우(예: 누락된 헤더로 인해) CamelExchangeException 예외를 발생시킵니다. ignoreInvalidExchanges 옵션을 사용하여 이러한 예외를 무시할 수 있습니다. 즉, resequencer는 잘못된 교환을 건너뜁니다.

from("direct:start")
  .resequence(header("seqno")).batch().timeout(1000)
    // ignore invalid exchanges (they are discarded)
    .ignoreInvalidExchanges()
  .to("mock:result");

8.6.6. 이전 메시지 거부

rejectOld 옵션을 사용하면 메시지를 다시 시작하는 데 사용되는 메커니즘에 관계없이 메시지가 순서대로 전송되는 것을 방지할 수 있습니다. rejectOld 옵션이 활성화되면 resequencer는 수신되는 메시지가 마지막 전달된 메시지보다 오래된 메시지(현재 비교기에 의해 정의됨)인 경우 수신되는 메시지를 거부합니다( MessageRejectedException 예외를 throw).

from("direct:start")
    .onException(MessageRejectedException.class).handled(true).to("mock:error").end()
    .resequence(header("seqno")).stream().timeout(1000).rejectOld()
    .to("mock:result");

8.7. 라우팅 슬립

8.7.1. 개요

그림 8.8. “라우팅 슬립 패턴” 에 표시된 라우팅 슬립 패턴을 사용하면 일련의 처리 단계를 통해 메시지를 연속으로 라우팅할 수 있습니다. 여기서 단계 시퀀스는 설계 시 알 수 없으며 각 메시지에 따라 다를 수 있습니다. 메시지가 전달되어야 하는 끝점 목록은 런타임에 Apache Camel이 읽고 즉시 파이프라인을 구성하기 위해 런타임에 읽는 헤더 필드( 슬립)에 저장됩니다.

그림 8.8. 라우팅 슬립 패턴

라우팅 슬립

8.7.2. slip 헤더

라우팅 슬립은 사용자 정의 헤더에 나타납니다. 여기서 헤더 값은 엔드포인트 URI의 쉼표로 구분된 목록입니다. 예를 들어, 보안 작업의 시퀀스를 지정하는 라우팅 슬립은 다음과 같습니다.For example, a routing slip that specifies a sequence of security tasks finishesdecrypting, authenticating, and de-duplicating a message Cryostat- Cryostatmight look like the following:

cxf:bean:decrypt,cxf:bean:authenticate,cxf:bean:dedup

8.7.3. 현재 끝점 속성

Camel 2.5에서 라우팅 Slip는 미끄러짐에 따라 현재 엔드 포인트가 포함된 교환에 속성(Exchange.SLIP_ENDPOINT)을 설정합니다. 이를 통해 교환이 슬립을 통해 얼마나 진행되었는지 확인할 수 있습니다.

8.7절. “라우팅 슬립”사전에 슬립을 계산하므로 슬립은 한 번만 계산됩니다. slip on-the-fly 를 계산해야 하는 경우 대신 8.18절. “동적 라우터” 패턴을 사용합니다.

8.7.4. Java DSL 예

다음 경로는 direct:a 끝점에서 메시지를 가져오고 aRoutingSlipHeader 헤더에서 라우팅 슬립을 읽습니다.

from("direct:b").routingSlip("aRoutingSlipHeader");

헤더 이름을 문자열 리터럴 또는 표현식으로 지정할 수 있습니다.

routingSlip() 의 2-argument 양식을 사용하여 URI 구분자를 사용자 지정할 수도 있습니다. 다음 예제에서는 라우팅 분할에 aRoutingSlipHeader 헤더 키를 사용하는 경로를 정의하고 # 문자를 URI 구분 기호로 사용합니다.

from("direct:c").routingSlip("aRoutingSlipHeader", "#");

8.7.5. XML 구성 예

다음 예제에서는 XML로 동일한 경로를 구성하는 방법을 보여줍니다.

<camelContext id="buildRoutingSlip" xmlns="http://camel.apache.org/schema/spring">
  <route>
    <from uri="direct:c"/>
    <routingSlip uriDelimiter="#">
      <headerName>aRoutingSlipHeader</headerName>
    </routingSlip>
  </route>
</camelContext>

8.7.6. 잘못된 끝점 무시

8.7절. “라우팅 슬립” 에서는 8.3절. “수신자 목록” 패턴에서도 지원하는 ignoreInvalidEndpoints 를 지원합니다. 이를 사용하여 유효하지 않은 엔드포인트를 건너뛸 수 있습니다. 예를 들면 다음과 같습니다.

    from("direct:a").routingSlip("myHeader").ignoreInvalidEndpoints();

Spring XML에서 이 기능은 < routingSlip > 태그에서 ignoreInvalidEndpoints 속성을 설정하여 활성화됩니다.

   <route>
       <from uri="direct:a"/>
       <routingSlip ignoreInvalidEndpoints="true">
         <headerName>myHeader</headerName>
       </routingSlip>
   </route>

myHeader 에 두 개의 끝점인 direct:foo,xxx:bar 가 포함된 경우를 고려하십시오. 첫 번째 끝점이 유효하고 작동합니다. 두 번째는 유효하지 않으므로 무시됩니다. 잘못된 엔드포인트가 발생할 때마다 INFO 수준에서 Apache Camel 로그를 기록합니다.

8.7.7. 옵션

routingSlip DSL 명령은 다음 옵션을 지원합니다.

이름

기본값

설명

uriDelimiter

,

Expression에서 여러 끝점을 반환한 경우 사용되는 구분 기호입니다.

ignoreInvalidEndpoints

false

엔드포인트 uri를 확인할 수 없는 경우 무시해야 합니다. 그렇지 않으면 Camel에서 엔드포인트 uri가 유효하지 않음을 나타내는 예외가 throw됩니다.

cacheSize

0

Camel 2.13.1/2.12.4: 라우팅 슬립에서 재사용할 생산자를 캐시하는 ProducerCache 의 캐시 크기를 구성할 수 있습니다. 기본적으로는 기본적으로 0인 기본 캐시 크기를 사용합니다. 값을 -1로 설정하면 캐시를 모두 해제할 수 있습니다.

8.8. Throttler

8.8.1. 개요

throttler 는 들어오는 메시지의 흐름 속도를 제한하는 프로세서입니다. 이 패턴을 사용하여 대상 끝점이 과부하되지 않도록 보호할 수 있습니다. Apache Camel에서는 throttle() Java DSL 명령을 사용하여 throttler 패턴을 구현할 수 있습니다.

8.8.2. Java DSL 예

흐름 속도를 초당 100개 메시지로 제한하려면 다음과 같이 경로를 정의합니다.

from("seda:a").throttle(100).to("seda:b");

필요한 경우 timePeriodMillis() DSL 명령을 사용하여 흐름 속도를 제어하는 기간을 사용자 지정할 수 있습니다. 예를 들어 흐름 속도를 30000밀리초당 3개의 메시지로 제한하려면 다음과 같이 경로를 정의합니다.

from("seda:a").throttle(3).timePeriodMillis(30000).to("mock:result");

8.8.3. XML 구성 예

다음 예제에서는 XML로 이전 경로를 구성하는 방법을 보여줍니다.

<camelContext id="throttleRoute" xmlns="http://camel.apache.org/schema/spring">
  <route>
    <from uri="seda:a"/>
    <!-- throttle 3 messages per 30 sec -->
    <throttle timePeriodMillis="30000">
      <constant>3</constant>
      <to uri="mock:result"/>
    </throttle>
  </route>
</camelContext>

8.8.4. 기간당 최대 요청 동적으로 변경

사용 가능한 Camel 2.8 since we use an Expression, you can adjust this value at runtime, for example you can provide a header with the value. 런타임 Camel에서 표현식을 평가하고 결과를 java.lang.Long 유형으로 변환합니다. 아래 예제에서는 메시지의 헤더를 사용하여 기간당 최대 요청을 결정합니다. 헤더가 없으면 8.8절. “Throttler” 에서 이전 값을 사용합니다. 따라서 값을 변경할 때만 헤더를 제공할 수 있습니다.

<camelContext id="throttleRoute" xmlns="http://camel.apache.org/schema/spring">
  <route>
    <from uri="direct:expressionHeader"/>
    <throttle timePeriodMillis="500">
      <!-- use a header to determine how many messages to throttle per 0.5 sec -->
      <header>throttleValue</header>
      <to uri="mock:result"/>
    </throttle>
  </route>
</camelContext>

8.8.5. 비동기 지연

throttler는 비차단 비동기 지연 을 활성화할 수 있습니다. 즉, Apache Camel에서 향후 실행될 작업을 예약합니다. 이 작업은 경로의 마지막 부분을 처리합니다( throttler 이후). 이를 통해 호출자 스레드는 수신되는 메시지를 차단 해제하고 추가로 서비스할 수 있습니다. 예를 들면 다음과 같습니다.

from("seda:a").throttle(100).asyncDelayed().to("seda:b");
참고

Camel 2.17에서 Throttler는 메시지 흐름을 개선하는 기간 동안 롤링 창을 사용합니다. 그러나 스로틀러의 성능이 향상됩니다.

8.8.6. 옵션

throttle DSL 명령은 다음 옵션을 지원합니다.

이름

기본값

설명

maximumRequestsPerPeriod

 

throttle까지의 기간당 최대 요청 수입니다. 이 옵션을 제공해야 하며 양수를 제공해야 합니다. Camel 2.8 이후의 XML DSL에서 이 옵션은 속성 대신 Expression을 사용하여 구성됩니다.

timePeriodMillis

1000

제한자가 최대 maximumRequestsPeriod 메시지 수를 허용하는 시간(밀리초 )입니다.

asyncDelayed

false

Camel 2.4: 활성화하면 예약된 스레드 풀을 사용하여 지연되는 모든 메시지가 비동기적으로 수행됩니다.

executorServiceRef

 

Camel 2.4: asyncDelay 가 활성화된 경우 사용할 사용자 정의 스레드 풀을 나타냅니다.

callerRunsWhenRejected

true

Camel 2.4: asyncDelayed 가 활성화된 경우 사용됩니다. 스레드 풀이 작업을 거부한 경우 호출자 스레드가 작업을 실행해야 하는지 여부를 제어합니다.

8.9. Delayer

8.9.1. 개요

지연은 들어오는 메시지에 상대 시간 지연을 적용할 수 있는 프로세서입니다.

8.9.2. Java DSL 예

delay() 명령을 사용하여 들어오는 메시지에 상대 시간 지연을 밀리초 단위로 추가할 수 있습니다. 예를 들어 다음 경로는 들어오는 모든 메시지를 2초로 지연합니다.

from("seda:a").delay(2000).to("mock:result");

또는 표현식을 사용하여 시간 지연을 지정할 수 있습니다.

from("seda:a").delay(header("MyDelay")).to("mock:result");

delay() 를 따르는 DSL 명령은 delay() 의 하위 항목으로 해석됩니다. 따라서 일부 컨텍스트에서 end() 명령을 삽입하여 delay()의 하위 항목을 종료할 필요가 있습니다. 예를 들어 delay()onException() 절 내에 표시되면 다음과 같이 종료합니다.

from("direct:start")
    .onException(Exception.class)
        .maximumRedeliveries(2)
        .backOffMultiplier(1.5)
        .handled(true)
        .delay(1000)
            .log("Halting for some time")
            .to("mock:halt")
        .end()
    .end()
    .to("mock:result");

8.9.3. XML 구성 예

다음 예제에서는 XML DSL의 지연을 보여줍니다.

<camelContext xmlns="http://camel.apache.org/schema/spring">
    <route>
        <from uri="seda:a"/>
        <delay>
            <header>MyDelay</header>
        </delay>
        <to uri="mock:result"/>
    </route>
    <route>
        <from uri="seda:b"/>
        <delay>
            <constant>1000</constant>
        </delay>
        <to uri="mock:result"/>
    </route>
</camelContext>

8.9.4. 사용자 정의 지연 생성

sum과 결합된 표현식을 사용하여 다음과 같이 지연을 확인할 수 있습니다.

from("activemq:foo").
  delay().expression().method("someBean", "computeDelay").
  to("activemq:bar");

다음처럼 Quarkus 클래스를 정의할 수 있는 위치는 다음과 같습니다.

public class SomeBean {
  public long computeDelay() {
     long delay = 0;
     // use java code to compute a delay value in millis
     return delay;
 }
}

8.9.5. 비동기 지연

지연 시간이 비동기 지연을 사용하도록 할 수 있습니다. 즉, Apache Camel에서 향후 실행될 작업을 예약합니다. 이 작업은 경로의 마지막 부분을 처리합니다(마운트 후). 이를 통해 호출자 스레드는 수신되는 메시지를 차단 해제하고 추가로 서비스할 수 있습니다. 예를 들면 다음과 같습니다.

from("activemq:queue:foo")
    .delay(1000)
    .asyncDelayed()
    .to("activemq:aDelayedQueue");

다음과 같이 XML DSL로 동일한 경로를 작성할 수 있습니다.

<route>
   <from uri="activemq:queue:foo"/>
   <delay asyncDelayed="true">
       <constant>1000</constant>
   </delay>
   <to uri="activemq:aDealyedQueue"/>
   </route>

8.9.6. 옵션

지연기 패턴은 다음 옵션을 지원합니다.

이름

기본값

설명

asyncDelayed

false

Camel 2.4: 활성화된 경우 예약된 스레드 풀을 사용하여 지연된 메시지가 비동기적으로 수행됩니다.

executorServiceRef

 

Camel 2.4: asyncDelay 가 활성화된 경우 사용할 사용자 정의 스레드 풀을 나타냅니다.

callerRunsWhenRejected

true

Camel 2.4: asyncDelayed 가 활성화된 경우 사용됩니다. 스레드 풀이 작업을 거부한 경우 호출자 스레드가 작업을 실행해야 하는지 여부를 제어합니다.

8.10. 로드 밸런서

8.10.1. 개요

로드 밸런서 패턴을 사용하면 다양한 로드 밸런싱 정책을 사용하여 메시지 처리를 여러 끝점 중 하나에 위임할 수 있습니다.

8.10.2. Java DSL 예

다음 경로는 라운드 로빈 로드 밸런싱 정책을 사용하여 대상 끝점 mock:x,mock:y,mock:z 사이에 수신 메시지를 배포합니다.

from("direct:start").loadBalance().roundRobin().to("mock:x", "mock:y", "mock:z");

8.10.3. XML 구성 예

다음 예제에서는 XML로 동일한 경로를 구성하는 방법을 보여줍니다.

<camelContext xmlns="http://camel.apache.org/schema/spring">
  <route>
    <from uri="direct:start"/>
    <loadBalance>
        <roundRobin/>
        <to uri="mock:x"/>
        <to uri="mock:y"/>
        <to uri="mock:z"/>
    </loadBalance>
  </route>
</camelContext>

8.10.4. 로드 밸런싱 정책

Apache Camel 로드 밸런서는 다음과 같은 로드 밸런싱 정책을 지원합니다.

8.10.5. 라운드 로빈

라운드 로빈 로드 밸런싱 정책은 모든 대상 끝점을 통해 사이클에서 들어오는 각 메시지를 다음 엔드포인트로 전송합니다. 예를 들어 대상 끝점 목록이, mock:x,mock:y,mock:z 인 경우 수신되는 메시지는 끝점의 다음 시퀀스로 전송됩니다. mock:x,mock:y,mock:x, mock:x ,mock: y 등.

다음과 같이 Java DSL에서 라운드 로빈 로드 밸런싱 정책을 지정할 수 있습니다.

from("direct:start").loadBalance().roundRobin().to("mock:x", "mock:y", "mock:z");

또는 다음과 같이 XML로 동일한 경로를 구성할 수 있습니다.

<camelContext xmlns="http://camel.apache.org/schema/spring">
  <route>
    <from uri="direct:start"/>
    <loadBalance>
        <roundRobin/>
        <to uri="mock:x"/>
        <to uri="mock:y"/>
        <to uri="mock:z"/>
    </loadBalance>
  </route>
</camelContext>

8.10.6. random

임의의 로드 밸런싱 정책은 지정된 목록에서 임의로 대상 끝점을 선택합니다.

다음과 같이 Java DSL에서 임의의 로드 밸런싱 정책을 지정할 수 있습니다.

from("direct:start").loadBalance().random().to("mock:x", "mock:y", "mock:z");

또는 다음과 같이 XML로 동일한 경로를 구성할 수 있습니다.

<camelContext xmlns="http://camel.apache.org/schema/spring">
  <route>
    <from uri="direct:start"/>
    <loadBalance>
        <random/>
        <to uri="mock:x"/>
        <to uri="mock:y"/>
        <to uri="mock:z"/>
    </loadBalance>
  </route>
</camelContext>

8.10.7. 고정

고정 로드 밸런싱 정책은 지정된 표현식의 해시 값을 계산하여 선택한 엔드포인트로 In 메시지를 보냅니다. 이 로드 밸런싱 정책의 장점은 동일한 값의 표현식이 항상 동일한 서버로 전송된다는 점입니다. 예를 들어 사용자 이름이 포함된 헤더에서 해시 값을 계산하면 특정 사용자의 메시지가 항상 동일한 대상 끝점으로 전송되도록 합니다. 다른 유용한 접근 방식은 들어오는 메시지에서 세션 ID를 추출하는 표현식을 지정하는 것입니다. 이렇게 하면 동일한 세션에 속하는 모든 메시지가 동일한 대상 끝점으로 전송됩니다.

다음과 같이 Java DSL에 고정 로드 밸런싱 정책을 지정할 수 있습니다.

from("direct:start").loadBalance().sticky(header("username")).to("mock:x", "mock:y", "mock:z");

또는 다음과 같이 XML로 동일한 경로를 구성할 수 있습니다.

<camelContext xmlns="http://camel.apache.org/schema/spring">
  <route>
    <from uri="direct:start"/>
    <loadBalance>
      <sticky>
        <correlationExpression>
          <simple>header.username</simple>
        </correlationExpression>
      </sticky>
      <to uri="mock:x"/>
      <to uri="mock:y"/>
      <to uri="mock:z"/>
    </loadBalance>
  </route>
</camelContext>
참고

장애 조치 로드 밸런서에 고정 옵션을 추가하면 로드 밸런서가 마지막으로 알려진 좋은 끝점에서 시작됩니다.

8.10.8. 주제

주제 부하 분산 정책은 나열된 모든 대상 끝점에 각 In 메시지의 복사본을 보냅니다( JMS 주제와 같이 모든 대상에 메시지를 효과적으로 브로드캐스트).

Java DSL을 사용하여 다음과 같이 주제 로드 밸런싱 정책을 지정할 수 있습니다.

from("direct:start").loadBalance().topic().to("mock:x", "mock:y", "mock:z");

또는 다음과 같이 XML로 동일한 경로를 구성할 수 있습니다.

<camelContext xmlns="http://camel.apache.org/schema/spring">
  <route>
    <from uri="direct:start"/>
    <loadBalance>
        <topic/>
        <to uri="mock:x"/>
        <to uri="mock:y"/>
        <to uri="mock:z"/>
    </loadBalance>
  </route>
</camelContext>

8.10.9. 페일오버

Apache Camel 2.0에서 사용 가능한 장애 조치 로드 밸런서는 처리 중에 예외적으로 Exchange가 실패한 경우 다음 프로세서를 시도할 수 있습니다. 장애 조치를 트리거하는 특정 예외 목록을 사용하여 장애 조치를 구성할 수 있습니다. 예외를 지정하지 않으면 예외를 통해 페일오버가 트리거됩니다. 장애 조치 로드 밸런서는 onException 예외 절과 일치하는 예외에 대해 동일한 전략을 사용합니다.

스트림을 사용하는 경우 스트림 캐싱 활성화

스트리밍을 사용하는 경우 장애 조치 로드 밸런서를 사용할 때 스트림 캐싱 을 활성화해야 합니다. 실패할 때 스트림을 다시 읽을 수 있도록 이 작업이 필요합니다.

장애 조치 로드 밸런서는 다음 옵션을 지원합니다.

옵션

유형

Default

설명

inheritErrorHandler

boolean

true

Camel 2.3: 경로에 구성된 errorHandler 사용 여부를 지정합니다. 다음 끝점으로 즉시 장애 조치하려면 이 옵션( false)을 비활성화해야 합니다. 이 옵션을 활성화하면 Apache Camel에서 먼저 errorHandler 를 사용하여 메시지를 처리하려고 합니다.

예를 들어 메시지를 다시 전달하고 시도 사이에 지연을 사용하도록 오류 처리기 를 구성할 수 있습니다. Apache Camel은 처음에 원래 엔드포인트로 다시 전달하려고 시도하며, errorHandler 가 소진된 경우에만 다음 끝점으로 장애 조치됩니다.

maximumFailoverAttempts

int

-1

Camel 2.3: 새 엔드포인트로 장애 조치하려는 최대 시도 횟수를 지정합니다. 값 0 에서는 장애 조치 시도가 이루어지지 않으며-1 은 장애 조치(failover) 시도 횟수가 없음을 의미합니다.

roundRobin

boolean

false

Camel 2.3: 장애 조치 로드 밸런서가 라운드 로빈 모드에서 작동하는지 여부를 지정합니다. 그렇지 않은 경우 새 메시지를 처리할 때 항상 첫 번째 끝점에서 시작됩니다. 즉, 모든 메시지의 맨 위에서 다시 시작됩니다. 라운드 로빈이 활성화된 경우 상태를 유지하고 라운드 로빈 방식으로 다음 엔드포인트를 계속합니다. 라운드 로빈을 사용하는 경우 마지막으로 알려진 양호한 엔드포인트를 사용하지 않는 경우 사용할 다음 끝점을 항상 선택합니다.

다음 예제는 IOException 예외가 발생한 경우에만 실패하도록 구성되어 있습니다.

from("direct:start")
    // here we will load balance if IOException was thrown
    // any other kind of exception will result in the Exchange as failed
    // to failover over any kind of exception we can just omit the exception
    // in the failOver DSL
    .loadBalance().failover(IOException.class)
        .to("direct:x", "direct:y", "direct:z");

다음과 같이 장애 조치할 여러 예외를 선택적으로 지정할 수 있습니다.

// enable redelivery so failover can react
errorHandler(defaultErrorHandler().maximumRedeliveries(5));

from("direct:foo")
    .loadBalance()
    .failover(IOException.class, MyOtherException.class)
    .to("direct:a", "direct:b");

다음과 같이 XML로 동일한 경로를 구성할 수 있습니다.

<route errorHandlerRef="myErrorHandler">
    <from uri="direct:foo"/>
    <loadBalance>
        <failover>
            <exception>java.io.IOException</exception>
            <exception>com.mycompany.MyOtherException</exception>
        </failover>
        <to uri="direct:a"/>
        <to uri="direct:b"/>
    </loadBalance>
</route>

다음 예제에서는 라운드 로빈 모드에서 장애 조치하는 방법을 보여줍니다.

from("direct:start")
    // Use failover load balancer in stateful round robin mode,
    // which means it will fail over immediately in case of an exception
    // as it does NOT inherit error handler. It will also keep retrying, as
    // it is configured to retry indefinitely.
    .loadBalance().failover(-1, false, true)
    .to("direct:bad", "direct:bad2", "direct:good", "direct:good2");

다음과 같이 XML로 동일한 경로를 구성할 수 있습니다.

<route>
    <from uri="direct:start"/>
    <loadBalance>
        <!-- failover using stateful round robin,
        which will keep retrying the 4 endpoints indefinitely.
        You can set the maximumFailoverAttempt to break out after X attempts -->
        <failover roundRobin="true"/>
        <to uri="direct:bad"/>
        <to uri="direct:bad2"/>
        <to uri="direct:good"/>
        <to uri="direct:good2"/>
    </loadBalance>
</route>

가능한 한 빨리 다음 끝점으로 장애 조치하려면 inheritErrorHandler=false 를 구성하여 inheritErrorHandler 를 비활성화할 수 있습니다. 오류 처리기를 비활성화하면 개입하지 않도록 할 수 있습니다. 이렇게 하면 장애 조치 로드 밸런서가 가능한 한 빨리 장애 조치(failover)를 처리할 수 있습니다. 또한 roundRobin 모드를 활성화하면 성공할 때까지 재시도됩니다. 그런 다음 최대FailoverAttempts 옵션을 높은 값으로 구성하여 결국 소진하고 실패하도록 할 수 있습니다.

8.10.10. weighted round robin 및 weighted random

일반적으로 개별 서버 처리 용량에 따라 부하를 배포하는 것이 좋습니다.In many enterprise environments, where server nodes of processing power are hosting services, it is usually preferable to distribute the load in accordance with the individual server processing capacityacities. 가중치가 지정된 라운드 로빈 알고리즘 또는 가중치가 지정된 임의 알고리즘을 사용하여 이 문제를 해결할 수 있습니다.

가중치가 지정된 부하 분산 정책을 사용하면 다른 서버와 관련하여 각 서버에 대한 처리 부하 분산 비율 을 지정할 수 있습니다. 이 값을 각 서버의 양의 처리 가중치로 지정할 수 있습니다. 숫자가 클수록 서버가 더 큰 부하를 처리할 수 있음을 나타냅니다. 처리 가중치는 다른 처리 끝점과 관련하여 각 처리 끝점의 페이로드 분배 비율을 결정하는 데 사용됩니다.

사용할 수 있는 매개변수는 다음 표에 설명되어 있습니다.

표 8.3. weighted Options

옵션유형Default설명

roundRobin

boolean

false

라운드 로빈의 기본값은 false 입니다. 이 설정 또는 매개변수가 없으면 사용된 로드 밸런싱 알고리즘은 random입니다.

distributionRatioDelimiter

문자열

,

distributionRatioDelimiterdistributionRatio 를 지정하는 데 사용되는 구분 기호입니다. 이 속성이 지정되지 않은 경우 쉼표는 기본 구분 기호입니다.

다음 Java DSL 예제에서는 가중치가 지정된 라운드 로빈 경로와 가중치가 지정된 임의 경로를 정의하는 방법을 보여줍니다.

// Java
// round-robin
from("direct:start")
  .loadBalance().weighted(true, "4:2:1" distributionRatioDelimiter=":")
  .to("mock:x", "mock:y", "mock:z");

//random
from("direct:start")
  .loadBalance().weighted(false, "4,2,1")
  .to("mock:x", "mock:y", "mock:z");

다음과 같이 라운드 로빈 경로를 XML로 구성할 수 있습니다.

<!-- round-robin -->
<route>
  <from uri="direct:start"/>
  <loadBalance>
    <weighted roundRobin="true" distributionRatio="4:2:1" distributionRatioDelimiter=":" />
    <to uri="mock:x"/>
    <to uri="mock:y"/>
    <to uri="mock:z"/>
  </loadBalance>
</route>

8.10.11. 사용자 정의 로드 밸런서

사용자 정의 로드 밸런서(예: 자체 구현)도 사용할 수 있습니다.

Java DSL을 사용하는 예:

from("direct:start")
     // using our custom load balancer
     .loadBalance(new MyLoadBalancer())
     .to("mock:x", "mock:y", "mock:z");

XML DSL을 사용하는 것과 동일한 예:

<!-- this is the implementation of our custom load balancer -->
 <bean id="myBalancer" class="org.apache.camel.processor.CustomLoadBalanceTest$MyLoadBalancer"/>

 <camelContext xmlns="http://camel.apache.org/schema/spring">
   <route>
     <from uri="direct:start"/>
     <loadBalance>
       <!-- refer to my custom load balancer -->
       <custom ref="myBalancer"/>
       <!-- these are the endpoints to balancer -->
       <to uri="mock:x"/>
       <to uri="mock:y"/>
       <to uri="mock:z"/>
     </loadBalance>
   </route>
 </camelContext>

위의 XML DSL에서 <custom>은 Camel 2.8 이상에서만 사용할 수 있습니다. 이전 릴리스에서는 다음과 같이 수행해야 합니다.

       <loadBalance ref="myBalancer">
         <!-- these are the endpoints to balancer -->
         <to uri="mock:x"/>
         <to uri="mock:y"/>
         <to uri="mock:z"/>
       </loadBalance>

사용자 정의 로드 밸런서를 구현하려면 LoadBalancerSupportSimpleLoadBalancerSupport 와 같은 일부 지원 클래스를 확장할 수 있습니다. 전자는 비동기 라우팅 엔진을 지원하며 후자는 그렇지 않습니다. 예를 들면 다음과 같습니다.

public static class MyLoadBalancer extends LoadBalancerSupport {

     public boolean process(Exchange exchange, AsyncCallback callback) {
         String body = exchange.getIn().getBody(String.class);
         try {
             if ("x".equals(body)) {
                 getProcessors().get(0).process(exchange);
             } else if ("y".equals(body)) {
                 getProcessors().get(1).process(exchange);
             } else {
                 getProcessors().get(2).process(exchange);
             }
         } catch (Throwable e) {
             exchange.setException(e);
         }
         callback.done(true);
         return true;
     }
 }

8.10.12. 회로 차단기

회로 차단기 로드 밸런서는 특정 예외에 대한 모든 호출을 모니터링하는 데 사용되는 상태 저장 패턴입니다. 처음에 회로 차단기는 폐쇄 상태에 있으며 모든 메시지를 전달합니다. 실패가 있고 임계값에 도달하면 state로 이동하고 halfOpenAfter 시간 초과에 도달할 때까지 모든 호출을 거부합니다. 시간 초과 후 새 호출이 있는 경우 회로 차단기는 모든 메시지를 전달합니다. 결과가 성공하면 회로 차단기가 닫힌 상태로 이동합니다. 그렇지 않으면 열린 상태로 돌아갑니다.

Java DSL 예:

from("direct:start").loadBalance()
    .circuitBreaker(2, 1000L, MyCustomException.class)
    .to("mock:result");

Spring XML 예:

<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
    <route>
    <from uri="direct:start"/>
    <loadBalance>
        <circuitBreaker threshold="2" halfOpenAfter="1000">
            <exception>MyCustomException</exception>
        </circuitBreaker>
        <to uri="mock:result"/>
    </loadBalance>
</route>
</camelContext>

8.11. Hystrix

8.11.1. 개요

Camel 2.18부터 사용 가능합니다.

Hystrix 패턴을 사용하면 애플리케이션이 Camel 경로에서 회로 차단기를 제공할 수 있는 networkshistrix와 통합할 수 있습니다. Hystrix는 대기 시간 및 내결함성 라이브러리입니다.

  • 원격 시스템, 서비스 및 타사 라이브러리에 대한 액세스 지점을 분리
  • 계단식 중지 실패
  • 오류가 발생할 수 있는 복잡한 분산 시스템에서 탄력성 활성화

maven을 사용하는 경우 pom.xml 파일에 다음 종속성을 추가하여 Hystrix를 사용합니다.

<dependency>
      <groupId>org.apache.camel</groupId>
      <artifactId>camel-hystrix</artifactId>
      <version>x.x.x</version>
      <!-- Specify the same version as your Camel core version. -->
</dependency>

8.11.2. Java DSL 예

다음은 인라인 대체 경로로 다시 대체하여 느린 작업으로부터 보호하는 Hystrix 엔드포인트를 보여주는 예입니다. 기본적으로 시간 초과 요청은 1000ms 이므로 HTTP 끝점이 성공할 수 있어야 합니다.

from("direct:start")
    .hystrix()
        .to("http://fooservice.com/slow")
    .onFallback()
        .transform().constant("Fallback message")
    .end()
    .to("mock:result");

8.11.3. XML 구성 예

다음은 동일한 예이지만 XML에서는 다음과 같습니다.

<camelContext xmlns="http://camel.apache.org/schema/spring">
  <route>
    <from uri="direct:start"/>
    <hystrix>
      <to uri="http://fooservice.com/slow"/>
      <onFallback>
        <transform>
          <constant>Fallback message</constant>
        </transform>
      </onFallback>
    </hystrix>
    <to uri="mock:result"/>
  </route>
</camelContext>

8.11.4. Hystrix 대체 기능 사용

onFallback() 메서드는 메시지를 변환하거나 빈을 호출하거나 폴백으로 다른 것을 호출할 수 있는 로컬 처리를 위한 것입니다. 네트워크를 통해 외부 서비스를 호출해야 하는 경우 첫 번째 명령 개체를 고갈하지 않도록 자체 스레드 풀을 사용하는 독립적인 HystrixCommand 개체에서 실행되는 onFallbackViaNetwork() 메서드를 사용해야 합니다.

8.11.5. Hystrix 구성 예

Hystrix에는 다음 섹션에 나열된 많은 옵션이 있습니다. 아래 예제에서는 상태가 이동될 때 다시 요청을 시도하기 전에 회로 차단기가 5초(기본값)가 아닌 10초 동안 실행 타임아웃을 설정하는 데 필요한 Java DSL을 보여줍니다.

from("direct:start")
    .hystrix()
        .hystrixConfiguration()
             .executionTimeoutInMilliseconds(5000).circuitBreakerSleepWindowInMilliseconds(10000)
        .end()
        .to("http://fooservice.com/slow")
    .onFallback()
        .transform().constant("Fallback message")
    .end()
    .to("mock:result");

다음은 동일한 예이지만 XML에서는 다음과 같습니다.

<camelContext xmlns="http://camel.apache.org/schema/spring">
<camelContext xmlns="http://camel.apache.org/schema/spring">
  <route>
    <from uri="direct:start"/>
    <hystrix>
      <hystrixConfiguration executionTimeoutInMilliseconds="5000" circuitBreakerSleepWindowInMilliseconds="10000"/>
      <to uri="http://fooservice.com/slow"/>
      <onFallback>
        <transform>
          <constant>Fallback message</constant>
        </transform>
      </onFallback>
    </hystrix>
    <to uri="mock:result"/>
  </route>
</camelContext>
 You can also configure Hystrix globally and then refer to that
configuration. For example:
<camelContext xmlns="http://camel.apache.org/schema/spring">
   <!-- This is a shared config that you can refer to from all Hystrix patterns. -->
   <hystrixConfiguration id="sharedConfig" executionTimeoutInMilliseconds="5000" circuitBreakerSleepWindowInMilliseconds="10000"/>

   <route>
         <from uri="direct:start"/>
         <hystrix hystrixConfigurationRef="sharedConfig">
         <to uri="http://fooservice.com/slow"/>
         <onFallback>
            <transform>
               <constant>Fallback message</constant>
            </transform>
         </onFallback>
      </hystrix>
      <to uri="mock:result"/>
   </route>
</camelContext>

8.11.6. 옵션

thshystrix 구성 요소는 다음 옵션을 지원합니다. Hystrix는 기본값을 제공합니다.

이름기본값유형설명

circuitBreakerEnabled

true

부울

회로 차단기가 상태를 추적하고 쇼크 요청을 이동하는 경우 단락 요청을 사용하는지 여부를 결정합니다.

circuitBreakerErrorThresholdPercentage

50

정수

회로가 열린 상태로 이동해야 하는 오류 백분율을 설정하고 폴백 논리에 대한 쇼트 서킷 요청을 시작합니다.

circuitBreakerForceClosed

false

부울

true 값은 회로 차단기가 오류 백분율에 관계없이 요청을 허용하는 closed 상태로 강제 적용합니다.

circuitBreakerForceOpen

false

부울

true 값은 회로 차단기가 모든 요청을 거부하는 열린(트립됨) 상태로 강제 적용합니다.

circuitBreakerRequestVolumeThreshold

20

정수

회로를 이동할 롤링 창에서 최소 요청 수를 설정합니다.

circuitBreakerSleepWindownInMilliseconds

5000

정수

회로를 추적한 후 요청을 거부한 후 시간을 설정합니다. 이 시간이 지나면 회로가 다시 종료되어야 하는지를 요청 시도가 허용됩니다.

commandKey

노드 ID

문자열

Hystrix 명령을 식별합니다. 이 옵션을 구성할 수 없습니다. 이 옵션은 항상 명령을 고유하게 만드는 노드 ID입니다.

corePoolSize

10

정수

코어 thread-pool 크기를 설정합니다. 동시에 실행할 수 있는 HystrixCommand 개체의 최대 수입니다.

executionIsolationSemaphoreMaxConcurrentRequests

10

정수

ExecutionIsolationStrategy.SEMAPHORE.NET Framework를 사용할 때 HystrixCommand.run() 메서드가 수행할 수 있는 최대 요청 수를 설정합니다.

executionIsolationStrategy

스레드

문자열

이러한 격리 전략 중 HystrixCommand.run() 가 를 사용하여 실행되는 것을 나타냅니다. THREAD 는 별도의 스레드에서 실행되며 동시 요청은 thread-pool의 스레드 수에 의해 제한됩니다. 호출 스레드에서 SEMAPHORE 가 실행되고 동시 요청은 세마포어 수에 의해 제한됩니다.

executionIsolationThreadInterruptOnTimeout

true

부울

시간 초과가 발생할 때 HystrixCommand.run() 실행이 중단되어야 하는지 여부를 나타냅니다.

executionTimeoutInMilliseconds

1000

정수

실행 완료를 위해 시간 초과를 밀리초 단위로 설정합니다.

executionTimeoutEnabled

true

부울

HystrixCommand.run() 의 실행이 시간 초과되어야 하는지 여부를 나타냅니다.

fallbackEnabled

true

부울

hy strixCommand.getFallback() 에 대한 호출이 실패 또는 거부될 때 시도되는지 여부를 결정합니다.

fallbackIsolationSemaphoreMaxConcurrentRequests

10

정수

HystrixCommand.getFallback() 메서드가 호출 스레드에서 수행할 수 있는 최대 요청 수를 설정합니다.

groupKey

CamelHystrix

문자열

통계 및 회로 차단기 속성의 상관 관계를 유지하는 데 사용되는 Hystrix 그룹을 식별합니다.

keepAliveTime

1

정수

연결 유지 시간을 분 단위로 설정합니다.

maxQueueSize

-1

정수

BlockingQueue 구현의 최대 큐 크기를 설정합니다.

metricsHealthSnapshotIntervalInMilliseconds

500

정수

상태 스냅샷을 사용하도록 허용하는 사이의 대기 시간(밀리초)을 설정합니다. 상태 스냅샷은 성공 및 오류 백분율을 계산하고 회로 차단기 상태에 영향을 미칩니다.

metricsRollingPercentileBucketSize

100

정수

버킷당 보관되는 최대 실행 횟수를 설정합니다. If more executions occur during the time they will wrap and start over-writing at the beginning of the bucket.

metricsRollingPercentileEnabled

true

부울

실행 대기 시간을 추적해야 하는지 여부를 나타냅니다. 대기 시간은 백분율로 계산됩니다. false 값은 요약 통계(mean, percentiles)가 -1로 반환됩니다.

metricsRollingPercentileWindowBuckets

6

정수

rollingPercentile 창이 분할될 버킷 수를 설정합니다.

metricsRollingPercentileWindowInMilliseconds

60000

정수

밀리초 단위로 백분위 계산을 허용하도록 실행 시간이 유지되는 롤링 창의 기간을 설정합니다.

metricsRollingStatisticalWindowBuckets

10

정수

롤링 통계 창이 분할되는 버킷 수를 설정합니다.

metricsRollingStatisticalWindowInMilliseconds

10000

정수

이 옵션과 다음 옵션은 HystrixCommandHystrixObservableCommand 실행에서 메트릭을 캡처하는 데 적용됩니다.

queueSizeRejectionThreshold

5

정수

큐 크기 거부 임계값 - CryostatmaxQueueSize 에 도달하지 않은 경우에도 거부가 발생하는 인위 최대 큐 크기를 설정합니다.

requestLogEnabled

true

부울

HystrixCommand 실행 및 이벤트를 HystrixRequestLog 에 로깅해야 하는지 여부를 나타냅니다.

threadPoolKey

null

문자열

이 명령을 실행해야 하는 thread-pool을 정의합니다. 기본적으로 이 키는 그룹 키와 동일한 키를 사용합니다.

threadPoolMetricsRollingStatisticalWindowBucket

10

정수

롤링 통계 창이 분할되는 버킷 수를 설정합니다.

threadPoolMetricsRollingStatisticalWindowInMilliseconds

10000

정수

통계 롤링 창의 기간을 밀리초 단위로 설정합니다. 스레드 풀에 대한 메트릭이 유지되는 시간입니다.

8.12. 서비스 호출

8.12.1. 개요

Camel 2.18부터 사용 가능합니다.

서비스 호출 패턴을 사용하면 분산 시스템에서 원격 서비스를 호출할 수 있습니다. 호출할 서비스는 Kubernetes, Consul, etcd 또는 Zookeeper와 같은 서비스 레지스트리에서 조회됩니다. 패턴은 서비스 레지스트리의 구성을 서비스 호출과 구분합니다.

Maven 사용자는 서비스 레지스트리를 사용하려면 종속성을 추가해야 합니다. 다음과 같은 가능성이 있습니다.

  • camel-consul
  • camel-etcd
  • camel-kubenetes
  • camel-ribbon

8.12.2. 서비스 호출 구문

서비스를 호출하려면 다음과 같이 서비스 이름을 참조하십시오.

from("direct:start")
    .serviceCall("foo")
    .to("mock:result");

다음 예제에서는 서비스를 호출하는 XML DSL을 보여줍니다.

<camelContext xmlns="http://camel.apache.org/schema/spring">
  <route>
    <from uri="direct:start"/>
    <serviceCall name="foo"/>
    <to uri="mock:result"/>
  </route>
</camelContext>

이 예제에서 Camel은 서비스 레지스트리와 통합된 구성 요소를 사용하여 foo 라는 이름으로 서비스를 조회합니다. 조회는 원격 서비스를 호스팅하는 활성 서버 목록을 참조하는 IP:PORT 쌍 세트를 반환합니다. 그런 다음 Camel은 사용할 서버를 무작위로 선택하여 선택한 IPPORT 번호로 Camel URI를 빌드합니다.

기본적으로 Camel은 HTTP 구성 요소를 사용합니다. 위의 예에서 호출은 다음과 같이 동적 toD 엔드포인트에서 호출하는 Camel URI로 확인됩니다.

toD("http://IP:PORT")
<toD uri="http:IP:port"/>

URI 매개변수를 사용하여 서비스를 호출할 수 있습니다(예: beer=yes ):

serviceCall("foo?beer=yes")
<serviceCall name="foo?beer=yes"/>

컨텍스트 경로를 제공할 수도 있습니다. 예를 들면 다음과 같습니다.

serviceCall("foo/beverage?beer=yes")
<serviceCall name="foo/beverage?beer=yes"/>

8.12.3. 서비스 이름을 URI로 변환

표시된 대로 서비스 이름은 Camel 엔드포인트 URI로 확인됩니다. 다음은 몇 가지 추가 예입니다. 은 Camel URI의 해상도를 보여줍니다.

serviceCall("myService") -> http://hostname:port
serviceCall("myService/foo") -> http://hostname:port/foo
serviceCall("http:myService/foo") -> http:hostname:port/foo
<serviceCall name="myService"/> -> http://hostname:port
<serviceCall name="myService/foo"/> -> http://hostname:port/foo
<serviceCall name="http:myService/foo"/> -> http:hostname:port/foo

확인된 URI를 완전히 제어하려면 원하는 Camel URI를 지정하는 추가 URI 매개변수를 제공합니다. 지정된 URI에서 IP:PORT 로 확인되는 서비스 이름을 사용할 수 있습니다. 다음은 몇 가지 예입니다.

serviceCall("myService", "http:myService.host:myService.port/foo") -> http:hostname:port/foo
serviceCall("myService", "netty4:tcp:myService?connectTimeout=1000") -> netty:tcp:hostname:port?connectTimeout=1000
<serviceCall name="myService" uri="http:myService.host:myService.port/foo"/> -> http:hostname:port/foo
<serviceCall name="myService" uri="netty4:tcp:myService?connectTimeout=1000"/> -> netty:tcp:hostname:port?connectTimeout=1000

위의 예제에서는 myService 라는 서비스를 호출합니다. 두 번째 매개 변수는 해결된 URI의 값을 제어합니다. 첫 번째 예제에서는 serviceName.hostserviceName.port 를 사용하여 IP 또는 PORT를 나타냅니다. serviceName 만 지정하면 IP:PORT 로 확인됩니다.

8.12.4. 서비스를 호출하는 구성 요소 구성

기본적으로 Camel은 HTTP 구성 요소를 사용하여 서비스를 호출합니다. 다음 예제와 같이 HTTP4 또는 Netty4 HTTP와 같은 다른 구성 요소 사용을 구성할 수 있습니다.

KubernetesConfigurationDefinition config = new KubernetesConfigurationDefinition();
config.setComponent("netty4-http");

// Register the service call configuration:
context.setServiceCallConfiguration(config);

from("direct:start")
    .serviceCall("foo")
    .to("mock:result");

다음은 XML DSL의 예입니다.

&lt;camelContext xmlns="http://camel.apache.org/schema/spring">
  &lt;kubernetesConfiguration id="kubernetes" component="netty4-http"/>
  &lt;route>
    &lt;from uri="direct:start"/>
    &lt;serviceCall name="foo"/>
    &lt;to uri="mock:result"/>
  &lt;/route>
&lt;/camelContext>

8.12.5. 모든 구현에서 공유하는 옵션

다음 옵션은 각 구현에 사용할 수 있습니다.

옵션

기본값

설명

clientProperty

 

사용 중인 서비스 호출 구현에 고유한 속성을 지정합니다. 예를 들어, journalctl 구현을 사용하는 경우 클라이언트 속성은 com.netf Cryostat.client.config.CommonClientConfigKey 에서 정의됩니다.

component

http

원격 서비스를 호출하는 데 사용할 기본 Camel 구성 요소를 설정합니다. netty4-http, jetty, restlet 또는 기타 구성 요소와 같은 구성 요소 사용을 구성할 수 있습니다. 서비스에서 HTTP 프로토콜을 사용하지 않는 경우 mqtt, jms, amqp와 같은 다른 구성 요소를 사용해야 합니다. 서비스 호출에 URI 매개변수를 지정하면 이 매개변수에 지정된 구성 요소가 기본값 대신 사용됩니다.

loadBalancerRef

 

사용할 사용자 지정 org.apache.camel.spi.ServiceCallLoadBalancer 로 참조를 설정합니다.

serverListStrategyRef

 

사용할 사용자 지정 org.apache.camel.spi.ServiceCallServerListStrategy 로 참조를 설정합니다.

8.12.6. Kubernetes를 사용할 때 서비스 호출 옵션

Kubernetes 구현에서는 다음 옵션을 지원합니다.

옵션

기본값

설명

apiVersion

 

클라이언트 조회를 사용할 때 Kubernetes API 버전입니다.

caCertData

 

클라이언트 조회를 사용할 때 인증 기관 데이터를 설정합니다.

caCertFile

 

클라이언트 조회를 사용할 때 파일에서 로드되는 인증 기관 데이터를 설정합니다.

clientCertData

 

클라이언트 조회를 사용할 때 클라이언트 인증서 데이터를 설정합니다.

clientCertFile

 

클라이언트 조회를 사용할 때 파일에서 로드되는 클라이언트 인증서 데이터를 설정합니다.

clientKeyAlgo

 

클라이언트 조회를 사용할 때 RSA와 같은 클라이언트 키 저장소 알고리즘을 설정합니다.

clientKeyData

 

클라이언트 조회를 사용할 때 클라이언트 키 저장소 데이터를 설정합니다.

clientKeyFile

 

클라이언트 조회를 사용할 때 파일에서 로드되는 클라이언트 키 저장소 데이터를 설정합니다.

clientKeyPassphrase

 

클라이언트 조회를 사용할 때 클라이언트 키 저장소 암호를 설정합니다.

dnsDomain

 

dns 조회에 사용할 DNS 도메인을 설정합니다.

lookup

환경

서비스를 찾는 데 사용되는 전략 선택 조회 전략에는 다음이 포함됩니다.

  • 환경 변수를 사용합니다.Use environment variables.
  • DNS Cryostat- Cryostat DNS 도메인 이름을 사용합니다.
  • Java 클라이언트를 사용하여 Kubernetes 마스터 API를 호출하고 서비스를 적극적으로 호스팅하는 서버를 쿼리합니다.

masterUrl

 

클라이언트 조회를 사용할 때 Kubernetes 마스터의 URL입니다.

네임스페이스

 

사용할 Kubernetes 네임스페이스입니다. 기본적으로 네임스페이스의 이름은 환경 변수 KUBERNETES_MASTER 에서 가져옵니다.

oauthToken

 

클라이언트 조회를 사용할 때 인증에 OAUTH 토큰(사용자 이름/암호 대신)을 설정합니다.

암호

 

클라이언트 조회를 사용할 때 인증 암호를 설정합니다.

trustCerts

false

클라이언트 조회를 사용할 때 신뢰 인증서 검사를 설정할지 여부를 설정합니다.

사용자 이름

 

클라이언트 조회를 사용할 때 인증 사용자 이름을 설정합니다.

8.13. 멀티 캐스트

8.13.1. 개요

그림 8.9. “멀티 캐스트 패턴” 에 표시된 멀티 캐스트 패턴은 InOut 메시지 교환 패턴과 호환되는 고정 대상 패턴을 사용하는 수신자 목록 의 변형입니다. 이는 InOnly 교환 패턴과만 호환되는 수신자 목록과 대조적입니다.

그림 8.9. 멀티 캐스트 패턴

멀티 캐스트 패턴

8.13.2. 사용자 정의 집계 전략이 있는 멀티 캐스트

멀티 캐스트 프로세서는 원래 요청(각 수신자마다 하나씩)에 대한 응답으로 여러 개의 Out 메시지를 수신하는 반면 원래 호출자는 단일 응답만 받을 수 있습니다. 따라서 메시지 교환의 응답 결과에는 고유 한 불일치가 있으며 이러한 불일치를 극복하려면 멀티 캐스트 프로세서에 사용자 지정 집계 전략을 제공해야 합니다. 집계 전략 클래스는 모든 외부 메시지를 단일 응답 메시지로 집계해야 합니다.

판매자가 판매자가 판매자 목록에 판매 항목을 제공하는 전자 유도 서비스의 예를 살펴보십시오. 구매자는 각각 항목에 대한 호의를하고, 판매자는 가장 높은 가격으로 호의를 자동으로 선택합니다. 다음과 같이 multicast() DSL 명령을 사용하여 고정 고객 목록에 제안을 배포하는 논리를 구현할 수 있습니다.

from("cxf:bean:offer").multicast(new HighestBidAggregationStrategy()).
    to("cxf:bean:Buyer1", "cxf:bean:Buyer2", "cxf:bean:Buyer3");

판매자가 엔드포인트, cxf:bean:offer 로 표시된 경우, 구매자는 엔드포인트, cxf:bean:Buyer1,cxf:bean:Buyer2,cxf:bean:Buyer3 로 표시됩니다. 멀티 캐스트 프로세서는 다양한 구매자로부터 수신된 호의를 통합하기 위해 집계 전략인 HighestBidAggregationStrategy 를 사용합니다. 다음과 같이 Java에서 HighestBidAggregationStrategy 를 구현할 수 있습니다.

// Java
import org.apache.camel.processor.aggregate.AggregationStrategy;
import org.apache.camel.Exchange;

public class HighestBidAggregationStrategy implements AggregationStrategy {
    public Exchange aggregate(Exchange oldExchange, Exchange newExchange) {
        float oldBid = oldExchange.getOut().getHeader("Bid", Float.class);
        float newBid = newExchange.getOut().getHeader("Bid", Float.class);
        return (newBid > oldBid) ? newExchange : oldExchange;
    }
}

구매자가 가맹점 ( Bid )이라는 헤더에 가망 가격을 삽입한다고 가정합니다. 사용자 정의 집계 전략에 대한 자세한 내용은 8.5절. “수집기” 을 참조하십시오.

8.13.3. 병렬 처리

기본적으로 멀티캐스트 프로세서는 수신자 엔드포인트를 각각 차례로 호출합니다( to() 명령에 나열된 순서대로). 경우에 따라 대기 시간이 오래 걸릴 수 있습니다. 이러한 긴 대기 시간을 방지하기 위해 parallelProcessing() 절을 추가하여 병렬 처리를 활성화할 수 있습니다. 예를 들어 전자 유도 예에서 병렬 처리를 활성화하려면 다음과 같이 경로를 정의합니다.

from("cxf:bean:offer")
    .multicast(new HighestBidAggregationStrategy())
        .parallelProcessing()
        .to("cxf:bean:Buyer1", "cxf:bean:Buyer2", "cxf:bean:Buyer3");

여기서 멀티 캐스트 프로세서는 이제 각 끝점에 대해 하나의 스레드가 있는 스레드 풀을 사용하여 구매자 끝점을 호출합니다.

구매자 엔드포인트를 호출하는 스레드 풀의 크기를 사용자 지정하려면 executorService() 메서드를 호출하여 자체 사용자 지정 executor 서비스를 지정할 수 있습니다. 예를 들면 다음과 같습니다.

from("cxf:bean:offer")
    .multicast(new HighestBidAggregationStrategy())
        .executorService(MyExecutor)
        .to("cxf:bean:Buyer1", "cxf:bean:Buyer2", "cxf:bean:Buyer3");

여기서 MyExecutorjava.util.concurrent.ExecutorService 유형의 인스턴스입니다.

교환에 InOut 패턴이 있으면 집계 전략이 사용하여 응답 메시지를 집계합니다. 기본 집계 전략에서는 최신 응답 메시지를 사용하고 이전 응답을 삭제합니다. 예를 들어 다음 경로에서 사용자 정의 전략 MyAggregationStrategy 는 끝점, direct:a,direct:bdirect:c 의 응답을 집계하는 데 사용됩니다.

from("direct:start")
  .multicast(new MyAggregationStrategy())
      .parallelProcessing()
      .timeout(500)
      .to("direct:a", "direct:b", "direct:c")
  .end()
  .to("mock:result");

8.13.4. XML 구성 예

다음 예제에서는 XML에서 유사한 경로를 구성하는 방법을 보여줍니다. 여기서 경로는 사용자 지정 집계 전략 및 사용자 지정 스레드 executor를 사용합니다.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
    ">

  <camelContext xmlns="http://camel.apache.org/schema/spring">
    <route>
      <from uri="cxf:bean:offer"/>
      <multicast strategyRef="highestBidAggregationStrategy"
                 parallelProcessing="true"
                 threadPoolRef="myThreadExcutor">
         <to uri="cxf:bean:Buyer1"/>
         <to uri="cxf:bean:Buyer2"/>
         <to uri="cxf:bean:Buyer3"/>
      </multicast>
    </route>
  </camelContext>

  <bean id="highestBidAggregationStrategy" class="com.acme.example.HighestBidAggregationStrategy"/>
  <bean id="myThreadExcutor" class="com.acme.example.MyThreadExcutor"/>

</beans>

여기서 parallelProcessing 특성과 threadPoolRef 속성은 선택 사항입니다. 멀티 캐스트 프로세서의 스레드 동작을 사용자 지정하려는 경우에만 설정해야 합니다.

8.13.5. 발신 메시지에 사용자 정의 처리 적용

멀티 캐스트 패턴은 소스 Exchange를 복사하고 복사본을 멀티 캐스트합니다. 기본적으로 라우터는 소스 메시지의 단순 복사본을 만듭니다. 부분 복사에서는 원본 메시지의 헤더와 페이로드가 참조로만 복사되므로 원본 메시지의 복사본이 연결됩니다. 멀티캐스트 메시지의 부분 복사본이 연결되므로 메시지 본문을 변경할 수 있는 경우 사용자 지정 처리를 적용할 수 없습니다. 하나의 엔드포인트로 전송된 사본에 적용되는 사용자 지정 처리는 다른 모든 엔드포인트에 전송된 사본에도 적용됩니다.

참고

멀티 캐스트 구문을 사용하면 멀티캐스트 절에서 프로세스 DSL 명령을 호출할 수 있지만 의미가 없으며 onPrepare 와 동일한 효과가 없습니다 (실제로 프로세스 DSL 명령은 영향을 미치지 않습니다).

8.13.6. onPrepare를 사용하여 메시지를 준비할 때 사용자 정의 논리 실행

각 메시지 복제본에 사용자 지정 처리를 엔드포인트로 보내기 전에 적용하려면 multicast 절에서 onPrepare DSL 명령을 호출할 수 있습니다. onPrepare 명령은 메시지가 부분 복사된 직후 그리고 메시지가 끝점으로 디스패치되기 직전에 사용자 지정 프로세서를 삽입합니다. 예를 들어 다음 경로에서 CustomProc 프로세서는 direct:a 로 전송된 메시지에 대해 호출되고 CustomProc 프로세서는 direct:b 로 전송된 메시지에서도 호출됩니다.

from("direct:start")
  .multicast().onPrepare(new CustomProc())
  .to("direct:a").to("direct:b");

onPrepare DSL 명령의 일반적인 사용 사례는 메시지의 일부 또는 모든 요소의 깊은 복사본을 수행하는 것입니다. 예를 들어 다음 CustomProc 프로세서 클래스는 메시지 본문의 깊은 복사본을 수행합니다. 여기서 메시지 본문은 유형인 BodyType.deepCopy()로 추정되고 깊은 복사는 메서드인 BodyType.deepCopy() 에 의해 수행됩니다.

// Java
import org.apache.camel.*;
...
public class CustomProc implements Processor {

    public void process(Exchange exchange) throws Exception {
        BodyType body = exchange.getIn().getBody(BodyType.class);

        // Make a _deep_ copy of of the body object
        BodyType clone =  BodyType.deepCopy();
        exchange.getIn().setBody(clone);

        // Headers and attachments have already been
        // shallow-copied. If you need deep copies,
        // add some more code here.
    }
}

onPrepare 를 사용하여 Exchange 가 멀티 캐스트이기 전에 실행할 모든 종류의 사용자 지정 논리를 구현할 수 있습니다.

참고

변경할 수 없는 오브젝트를 설계하는 것이 좋습니다.

예를 들어 이 Animal 클래스로 변경할 수 있는 메시지 본문이 있는 경우 다음을 수행합니다.

public class Animal implements Serializable {

     private int id;
     private String name;

     public Animal() {
     }

     public Animal(int id, String name) {
         this.id = id;
         this.name = name;
     }

     public Animal deepClone() {
         Animal clone = new Animal();
         clone.setId(getId());
         clone.setName(getName());
         return clone;
     }

     public int getId() {
         return id;
     }

     public void setId(int id) {
         this.id = id;
     }

     public String getName() {
         return name;
     }

     public void setName(String name) {
         this.name = name;
     }

     @Override
     public String toString() {
         return id + " " + name;
     }
 }

그런 다음 메시지 본문을 복제하는 깊은 복제 프로세서를 생성할 수 있습니다.

public class AnimalDeepClonePrepare implements Processor {

     public void process(Exchange exchange) throws Exception {
         Animal body = exchange.getIn().getBody(Animal.class);

         // do a deep clone of the body which wont affect when doing multicasting
         Animal clone = body.deepClone();
         exchange.getIn().setBody(clone);
     }
 }

그런 다음 onPrepare 옵션을 사용하여 멀티 캐스트 경로에서 AnimalDeepClonePrepare 클래스를 사용할 수 있습니다.

from("direct:start")
     .multicast().onPrepare(new AnimalDeepClonePrepare()).to("direct:a").to("direct:b");

XML DSL의 동일한 예

<camelContext xmlns="http://camel.apache.org/schema/spring">
     <route>
         <from uri="direct:start"/>
         <!-- use on prepare with multicast -->
         <multicast onPrepareRef="animalDeepClonePrepare">
             <to uri="direct:a"/>
             <to uri="direct:b"/>
         </multicast>
     </route>

     <route>
         <from uri="direct:a"/>
         <process ref="processorA"/>
         <to uri="mock:a"/>
     </route>
     <route>
         <from uri="direct:b"/>
         <process ref="processorB"/>
         <to uri="mock:b"/>
     </route>
 </camelContext>

 <!-- the on prepare Processor which performs the deep cloning -->
 <bean id="animalDeepClonePrepare" class="org.apache.camel.processor.AnimalDeepClonePrepare"/>

 <!-- processors used for the last two routes, as part of unit test -->
 <bean id="processorA" class="org.apache.camel.processor.MulticastOnPrepareTest$ProcessorA"/>
 <bean id="processorB" class="org.apache.camel.processor.MulticastOnPrepareTest$ProcessorB"/>

8.13.7. 옵션

멀티 캐스트 DSL 명령은 다음 옵션을 지원합니다.

이름

기본값

설명

strategyRef

 

멀티 캐스트의 응답을 멀티 캐스트에서 보내는 단일 메시지로 어셈블하는 데 사용되는 집계Strategy 를 나타냅니다. ??? 기본적으로 Camel은 마지막 응답을 발신 메시지로 사용합니다.

strategyMethodName

 

이 옵션을 사용하면 Cryostat를 AggregationStrategy 로 사용할 메서드 이름을 명시적으로 지정할 수 있습니다.

strategyMethodAllowNull

false

이 옵션은 Cryostat를 AggregationStrategy 로 사용할 때 사용할 수 있습니다. false 인 경우 보강할 데이터가 없는 경우 집계 방법이 사용되지 않습니다. true 인 경우 보강할 데이터가 없는 경우 oldExchangenull 값이 사용됩니다.

parallelProcessing

false

활성화된 경우 멀티캐스트로 메시지를 동시에 보냅니다. 호출자 스레드는 계속 진행하기 전에 모든 메시지가 완전히 처리될 때까지 대기합니다. 동시에 발생하는 멀티 캐스트에서 응답을 전송 및 처리하는 경우에만 해당합니다.

parallelAggregate

false

활성화하면 AggregationStrategy집계 메서드를 동시에 호출할 수 있습니다. 이를 위해서는 스레드로부터 안전한 AggregationStrategy 를 구현해야 합니다. 기본적으로 이 옵션은 false 입니다. 즉, Camel이 집계 메서드에 자동으로 호출을 동기화합니다. 그러나 일부 사용 사례에서는 AggregationStrategy 를 스레드로부터 안전한 것으로 구현하고 이 옵션을 true 로 설정하여 성능을 향상시킬 수 있습니다.

executorServiceRef

 

병렬 처리에 사용할 사용자 지정 스레드 풀을 나타냅니다.Indicates to a custom Thread Pool to be used for parallel processing. 이 옵션을 설정하면 병렬 처리가 자동으로 표시되고 해당 옵션도 활성화할 필요가 없습니다.

stopOnException

false

Camel 2.2: 예외가 발생한 경우 즉시 처리를 중지해야 하는지의 여부입니다. disable인 경우 Camel은 실패했는지에 관계없이 모든 멀티캐스트로 메시지를 보냅니다. 이를 처리하는 방법을 완전히 제어하는 AggregationStrategy 클래스에서 예외를 처리할 수 있습니다.

스트리밍

false

활성화된 경우 Camel은 주문 외 응답(예: 다시 들어오는 순서)을 처리합니다. 비활성화된 경우 Camel은 멀티 캐스트와 동일한 순서로 응답을 처리합니다.

timeout

 

Camel 2.5: 밀리초 단위로 지정된 총 타임아웃을 설정합니다. 멀티캐스트 가 지정된 시간 내에 모든 응답을 전송 및 처리할 수 없는 경우 시간 초과 트리거와 멀티캐스트 가 중단되고 계속됩니다. TimeoutAwareAggregationStrategy 를 제공하면 중단하기 전에 timeout 메서드가 호출됩니다.

onPrepareRef

 

Camel 2.8: 사용자 지정 프로세서를 참조하여 각 멀티 캐스트가 수신하는 교환 사본을 준비합니다. 이를 통해 필요한 경우 메시지 페이로드를 깊이 복제하는 등 사용자 지정 논리를 수행할 수 있습니다.

shareUnitOfWork

false

Camel 2.8: 작업 단위를 공유해야 하는지 여부입니다. 자세한 내용은 8.4절. “Splitter” 에서 동일한 옵션을 참조하십시오.

8.14. 구성된 메시지 프로세서

8.14.1. 구성된 메시지 프로세서

그림 8.10. “구성된 메시지 프로세서 패턴” 에 표시된 대로 구성된 메시지 프로세서 패턴을 사용하면 이를 분할하고 하위 메시지를 적절한 대상으로 라우팅한 다음 응답을 단일 메시지로 다시 집계하여 복합 메시지를 처리할 수 있습니다.

그림 8.10. 구성된 메시지 프로세서 패턴

배포 집계

8.14.2. Java DSL 예

다음 예제에서는 주문의 각 부분을 다른 인벤토리에서 확인해야 하는 다중 파트 순서를 채울 수 있는지 확인합니다.

// split up the order so individual OrderItems can be validated by the appropriate bean
from("direct:start")
    .split().body()
    .choice()
        .when().method("orderItemHelper", "isWidget")
            .to("bean:widgetInventory")
        .otherwise()
            .to("bean:gadgetInventory")
    .end()
    .to("seda:aggregate");

// collect and re-assemble the validated OrderItems into an order again
from("seda:aggregate")
    .aggregate(new MyOrderAggregationStrategy())
    .header("orderId")
    .completionTimeout(1000L)
    .to("mock:result");

8.14.3. XML DSL 예

이전 경로는 다음과 같이 XML DSL로 작성할 수도 있습니다.

 <route>
   <from uri="direct:start"/>
   <split>
     <simple>body</simple>
     <choice>
       <when>
         <method bean="orderItemHelper" method="isWidget"/>
 	<to uri="bean:widgetInventory"/>
       </when>
       <otherwise>
 	<to uri="bean:gadgetInventory"/>
       </otherwise>
     </choice>
     <to uri="seda:aggregate"/>
   </split>
 </route>

 <route>
   <from uri="seda:aggregate"/>
   <aggregate strategyRef="myOrderAggregatorStrategy" completionTimeout="1000">
     <correlationExpression>
       <simple>header.orderId</simple>
     </correlationExpression>
     <to uri="mock:result"/>
   </aggregate>
 </route>

8.14.4. 처리 단계

처리는 8.4절. “Splitter” 을 사용하여 순서를 분할하여 시작합니다. 그러면 8.4절. “Splitter” 에서 개별 OrderItems 를 항목 유형에 따라 메시지를 라우팅하는 8.1절. “콘텐츠 기반 라우터” 로 보냅니다. 위젯 항목은 위젯 인벤토리 빈에서 확인할 수 있도록 전송되며 가젯 항목은 가젯 인벤토리 빈으로 전송됩니다. 이러한 OrderItems 의 유효성을 검사한 후 적절한 8080에서 8.5절. “수집기” 로 전송되어 검증된 OrderItems 를 다시 주문으로 수집하고 재조정합니다.

각 수신된 순서에는 주문 ID 가 포함된 헤더가 있습니다. 집계 단계에서 주문 ID를 사용합니다. aggregate() DSL 명령에 .header("orderId") 한정자를 사용하여 키, orderId 와 함께 헤더를 사용하도록 지시합니다.

자세한 내용은 camel-core/src/test/java/org/apache/camel/processor 에서 ComposedMessageProcessorTest.java 예제 소스를 확인하십시오.

8.15. together-Gather

8.15.1. together-Gather

그림 8.11. “Earge-Gather Pattern” 에 표시된 대로, together -gather 패턴 을 사용하면 동적으로 지정된 수의 수신자에게 메시지를 라우팅하고 응답을 단일 메시지로 다시 집계할 수 있습니다.

그림 8.11. Earge-Gather Pattern

브로드캐스트 집계

8.15.2. dynamic together-gather 예

다음 예제에서는 여러 다른 공급 업체에서 베터에 가장 적합한 인용을 가져오는 애플리케이션을 간략하게 설명합니다. 이 예제에서는 동적 8.3절. “수신자 목록” 를 사용하여 모든 공급업체의 인용문을 요청하고 8.5절. “수집기” 를 사용하여 모든 응답에서 가장 적합한 인용문을 선택합니다. 이 애플리케이션의 경로는 다음과 같이 정의됩니다.

<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
  <route>
    <from uri="direct:start"/>
    <recipientList>
      <header>listOfVendors</header>
    </recipientList>
  </route>
  <route>
    <from uri="seda:quoteAggregator"/>
    <aggregate strategyRef="aggregatorStrategy" completionTimeout="1000">
      <correlationExpression>
        <header>quoteRequestId</header>
      </correlationExpression>
      <to uri="mock:result"/>
    </aggregate>
  </route>
</camelContext>

첫 번째 경로에서 8.3절. “수신자 목록”listOfVendors 헤더를 보고 수신자 목록을 가져옵니다. 따라서 이 애플리케이션에 메시지를 보내는 클라이언트는 listOfVendors 헤더를 메시지에 추가해야 합니다. 예 8.1. “메시징 클라이언트 샘플” 발신 메시지에 관련 헤더 데이터를 추가하는 메시징 클라이언트의 일부 샘플 코드를 보여줍니다.

예 8.1. 메시징 클라이언트 샘플

Map<String, Object> headers = new HashMap<String, Object>();
headers.put("listOfVendors", "bean:vendor1, bean:vendor2, bean:vendor3");
headers.put("quoteRequestId", "quoteRequest-1");
template.sendBodyAndHeaders("direct:start", "<quote_request item=\"beer\"/>", headers);

message는 metrics: vendor1 ,MeshMemberRoll:vendor:vendor:vendor 2, blank :vendor3 끝점에 배포됩니다. 이러한 빈은 모두 다음 클래스로 구현됩니다.

public class MyVendor {
    private int beerPrice;

    @Produce(uri = "seda:quoteAggregator")
    private ProducerTemplate quoteAggregator;

    public MyVendor(int beerPrice) {
        this.beerPrice = beerPrice;
    }

    public void getQuote(@XPath("/quote_request/@item") String item, Exchange exchange) throws Exception {
        if ("beer".equals(item)) {
            exchange.getIn().setBody(beerPrice);
            quoteAggregator.send(exchange);
        } else {
            throw new Exception("No quote available for " + item);
        }
    }
}

polkit 인스턴스, vendor1,vendor2vendor3 은 다음과 같이 Spring XML 구문을 사용하여 인스턴스화됩니다.

<bean id="aggregatorStrategy" class="org.apache.camel.spring.processor.scattergather.LowestQuoteAggregationStrategy"/>

<bean id="vendor1" class="org.apache.camel.spring.processor.scattergather.MyVendor">
  <constructor-arg>
    <value>1</value>
  </constructor-arg>
</bean>

<bean id="vendor2" class="org.apache.camel.spring.processor.scattergather.MyVendor">
  <constructor-arg>
    <value>2</value>
  </constructor-arg>
</bean>

<bean id="vendor3" class="org.apache.camel.spring.processor.scattergather.MyVendor">
  <constructor-arg>
    <value>3</value>
  </constructor-arg>
</bean>

각 Cryostat는 더의 경우 다른 가격으로 초기화됩니다(생성자 인수로 전달됨). 메시지가 각 8080 끝점으로 전송되면 MyVendor.getQuote 메서드에 도달합니다. 이 방법은 이 인용 요청이 베터인지 여부를 확인하기 위한 간단한 검사를 수행한 다음 이후 단계에서 검색을 위해 교환에 대한 beer의 가격을 설정합니다. message는 Cryostat Producing을 사용하여 다음 단계로 전달됩니다(@Produce 주석 참조).

다음 단계에서 모든 공급 업체에서 beer 따옴표를 가져 와서 어느 것이 가장 좋은지 (즉, 가장 낮은)를 찾고 싶습니다. 이를 위해 사용자 정의 집계 전략과 함께 8.5절. “수집기” 를 사용합니다. 8.5절. “수집기” 는 현재 인용문과 관련된 메시지를 식별해야 합니다. 이 메시지는 quoteRequestId 헤더의 값에 따라 메시지를 순환하여 수행됩니다(concience Expression에 전달됨). 예 8.1. “메시징 클라이언트 샘플” 에 표시된 대로 상관 관계 ID는 quoteRequest-1 로 설정됩니다(관계 ID는 고유해야 함). 세트 중 가장 낮은 인용문을 선택하려면 다음과 같이 사용자 정의 집계 전략을 사용할 수 있습니다.

public class LowestQuoteAggregationStrategy implements AggregationStrategy {
    public Exchange aggregate(Exchange oldExchange, Exchange newExchange) {
        // the first time we only have the new exchange
        if (oldExchange == null) {
            return newExchange;
        }

        if (oldExchange.getIn().getBody(int.class) < newExchange.getIn().getBody(int.class)) {
            return oldExchange;
        } else {
            return newExchange;
        }
    }
}

8.15.3. 정적 together-gather 예

정적 8.3절. “수신자 목록” 을 사용하여 receiver를 명시적으로 지정할 수 있습니다. 다음 예제에서는 정적 192.0.2.-gather 시나리오를 구현하는 데 사용할 경로를 보여줍니다.

from("direct:start").multicast().to("seda:vendor1", "seda:vendor2", "seda:vendor3");

from("seda:vendor1").to("bean:vendor1").to("seda:quoteAggregator");
from("seda:vendor2").to("bean:vendor2").to("seda:quoteAggregator");
from("seda:vendor3").to("bean:vendor3").to("seda:quoteAggregator");

from("seda:quoteAggregator")
    .aggregate(header("quoteRequestId"), new LowestQuoteAggregationStrategy()).to("mock:result")

8.16. loop

8.16.1. loop

반복문 패턴을 사용하면 메시지를 여러 번 처리할 수 있습니다. 이는 주로 테스트에 사용됩니다.

기본적으로 루프는 루프 전체에서 동일한 교환을 사용합니다. 이전 반복의 결과는 다음에 사용됩니다( 5.4절. “파이프 및 필터”참조). Camel 2.8 의 경우 대신 복사 모드를 활성화할 수 있습니다. 자세한 내용은 options 표를 참조하십시오.

8.16.2. 속성 교환

각 루프 반복에서 두 개의 교환 속성이 설정되며 루프에 포함된 모든 프로세서에서 선택적으로 읽을 수 있습니다.

속성설명

CamelLoopSize

Apache Camel 2.0: 총 루프 수

CamelLoopIndex

Apache Camel 2.0: 현재 반복(0 기반)의 인덱스

8.16.3. Java DSL 예

다음 예제에서는 direct:x 끝점에서 요청을 가져온 다음 메시지를 mock:result 로 반복적으로 전송하는 방법을 보여줍니다. 루프 반복 수는 loop() 에 대한 인수로 지정되거나 런타임에 표현식을 평가하여 지정됩니다. 여기서 표현식은 int (또는 RuntimeCamelException 이 throw됨)로 평가 되어야 합니다.

다음 예제에서는 루프 수를 상수로 전달합니다.

from("direct:a").loop(8).to("mock:result");

다음 예제에서는 간단한 표현식을 평가하여 루프 수를 결정합니다.

from("direct:b").loop(header("loop")).to("mock:result");

다음 예제에서는 Cryostat 표현식을 평가하여 루프 수를 결정합니다.

from("direct:c").loop().xpath("/hello/@times").to("mock:result");

8.16.4. XML 구성 예

Spring XML에서 동일한 경로를 구성할 수 있습니다.

다음 예제에서는 루프 수를 상수로 전달합니다.

<route>
  <from uri="direct:a"/>
  <loop>
    <constant>8</constant>
    <to uri="mock:result"/>
  </loop>
</route>

다음 예제에서는 간단한 표현식을 평가하여 루프 수를 결정합니다.

<route>
  <from uri="direct:b"/>
  <loop>
    <header>loop</header>
    <to uri="mock:result"/>
  </loop>
</route>

8.16.5. 복사 모드 사용

이제 문자 A가 포함된 direct:start 끝점에 메시지를 보냅니다. 이 경로를 처리하는 출력은 각 mock:loop 끝점이 메시지로 AB를 수신합니다.

from("direct:start")
     // instruct loop to use copy mode, which mean it will use a copy of the input exchange
     // for each loop iteration, instead of keep using the same exchange all over
     .loop(3).copy()
         .transform(body().append("B"))
         .to("mock:loop")
     .end()
     .to("mock:result");

그러나 복사 모드를 활성화 하지 않으면 mock:loop 는 AB, A Cryostat, AB Cryostat 메시지를 수신합니다.

from("direct:start")
     // by default loop will keep using the same exchange so on the 2nd and 3rd iteration its
     // the same exchange that was previous used that are being looped all over
     .loop(3)
         .transform(body().append("B"))
         .to("mock:loop")
     .end()
     .to("mock:result");

복사 모드에서 XML DSL의 동등한 예는 다음과 같습니다.

<route>
   <from uri="direct:start"/>
   <!-- enable copy mode for loop eip -->
   <loop copy="true">
     <constant>3</constant>
     <transform>
       <simple>${body}B</simple>
     </transform>
     <to uri="mock:loop"/>
   </loop>
   <to uri="mock:result"/>
 </route>

8.16.6. 옵션

loop DSL 명령은 다음 옵션을 지원합니다.

이름

기본값

설명

복사

false

Camel 2.8: 복사 모드 사용 여부입니다. false 인 경우 루프 전체에서 동일한 교환이 사용됩니다. 따라서 이전 반복의 결과는 다음 반복에 대해 표시됩니다. 대신 복사 모드를 활성화한 다음 입력 “교환” 의 새 복사본 을 사용하여 각 반복이 다시 시작됩니다.

8.16.7. Do While Cryostat

do while 루프를 사용하여 조건이 충족될 때까지 루프를 수행할 수 있습니다. 조건은 true 또는 false입니다.

DSL에서 명령은 os DoWhile 입니다. 다음 예제에서는 메시지 본문 길이가 5자 이하가 될 때까지 루프를 수행합니다.

from("direct:start")
    .loopDoWhile(simple("${body.length} <= 5"))
        .to("mock:loop")
        .transform(body().append("A"))
    .end()
    .to("mock:result");

XML에서 명령은 loop doWhile 입니다. 다음 예제에서는 메시지 본문 길이가 5자 이하가 될 때까지 루프를 수행합니다.

<route>
  <from uri="direct:start"/>
  <loop doWhile="true">
    <simple>${body.length} <= 5</simple>
    <to uri="mock:loop"/>
    <transform>
      <simple>A${body}</simple>
    </transform>
  </loop>
  <to uri="mock:result"/>
</route>

8.17. sampling

8.17.1. sampling Throttler

샘플링 throttler를 사용하면 경로를 통해 트래픽에서 교환 샘플을 추출할 수 있습니다. 단일 교환만 통과할 수 있는 샘플링 기간으로 구성됩니다. 다른 모든 교환은 중단될 것입니다.

기본적으로 샘플 기간은 1초입니다.

8.17.2. Java DSL 예

다음과 같이 sample() DSL 명령을 사용하여 샘플러를 호출합니다.

// Sample with default sampling period (1 second)
from("direct:sample")
    .sample()
    .to("mock:result");

// Sample with explicitly specified sample period
from("direct:sample-configured")
    .sample(1, TimeUnit.SECONDS)
    .to("mock:result");

// Alternative syntax for specifying sampling period
from("direct:sample-configured-via-dsl")
    .sample().samplePeriod(1).timeUnits(TimeUnit.SECONDS)
    .to("mock:result");

from("direct:sample-messageFrequency")
    .sample(10)
    .to("mock:result");

from("direct:sample-messageFrequency-via-dsl")
    .sample().sampleMessageFrequency(5)
    .to("mock:result");

8.17.3. Spring XML 예

Spring XML에서 샘플 요소를 사용하여 sampler를 호출합니다. 여기서 samplePeriodunits 특성을 사용하여 샘플링 기간을 지정할 수 있습니다.

<route>
    <from uri="direct:sample"/>
    <sample samplePeriod="1" units="seconds">
        <to uri="mock:result"/>
    </sample>
</route>
<route>
    <from uri="direct:sample-messageFrequency"/>
    <sample messageFrequency="10">
        <to uri="mock:result"/>
    </sample>
</route>
<route>
    <from uri="direct:sample-messageFrequency-via-dsl"/>
    <sample messageFrequency="5">
        <to uri="mock:result"/>
    </sample>
</route>

8.17.4. 옵션

샘플 DSL 명령은 다음 옵션을 지원합니다.

이름

기본값

설명

messageFrequency

 

N번째 메시지마다 메시지를 샘플링합니다. 빈도 또는 기간 중 하나만 사용할 수 있습니다.

samplePeriod

1

N번째 기간마다 메시지를 샘플링합니다. 빈도 또는 기간 중 하나만 사용할 수 있습니다.

단위

SECOND

JDK에서 java.util.concurrent.TimeUnit 의 시간 단위입니다.

8.18. 동적 라우터

8.18.1. 동적 라우터

그림 8.12. “동적 라우터 패턴” 에 표시된 대로 동적 라우터 패턴을 사용하면 설계 시 단계 시퀀스를 알 수 없는 일련의 처리 단계를 통해 메시지를 연속으로 라우팅할 수 있습니다. 메시지가 전달되어야 하는 끝점 목록은 런타임에 동적으로 계산됩니다. 메시지가 끝점에서 반환될 때마다 동적 라우터는 8080에서 다시 호출하여 경로의 다음 엔드포인트를 검색합니다.

그림 8.12. 동적 라우터 패턴

동적 라우터

Camel 2.5 에서는 DSL에 동적Router 를 도입했습니다. 이 DSL은 플립을 즉시 평가하는 동적 8.7절. “라우팅 슬립” 과 같습니다.

참고

dynamicRouter (예: 8080)에 사용된 표현식이 null 을 반환하여 끝을 표시해야 합니다. 그렇지 않으면 dynamicRouter 가 끝없는 루프에서 계속됩니다.

8.18.2. Camel 2.5 이후의 동적 라우터

Camel 2.5에서 8.18절. “동적 라우터” 는 교환 속성인 Exchange.SLIP_ENDPOINT 를 업데이트하며, 슬립이 진행됨에 따라 현재 끝점을 업데이트합니다. 이를 통해 교환이 슬립을 통해 얼마나 진행되었는지 확인할 수 있습니다. 8.18절. “동적 라우터” 구현은 8.7절. “라우팅 슬립”을 기반으로 하므로 슬립입니다.

8.18.3. Java DSL

Java DSL에서는 다음과 같이 dynamicRouter 를 사용할 수 있습니다.

from("direct:start")
    // use a bean as the dynamic router
    .dynamicRouter(bean(DynamicRouterTest.class, "slip"));

빈 통합을 활용하여 다음과 같이 구현할 수 있는 on-the-fly 를 계산합니다.

// Java
/**
 * Use this method to compute dynamic where we should route next.
 *
 * @param body the message body
 * @return endpoints to go, or <tt>null</tt> to indicate the end
 */
public String slip(String body) {
    bodies.add(body);
    invoked++;

    if (invoked == 1) {
        return "mock:a";
    } else if (invoked == 2) {
        return "mock:b,mock:c";
    } else if (invoked == 3) {
        return "direct:foo";
    } else if (invoked == 4) {
        return "mock:result";
    }

    // no more so return null
    return null;
    }
참고

위 예제는 스레드로부터 안전하지 않습니다. 스레드의 안전성을 보장하기 위해 Exchange 에 상태를 저장해야 합니다.

8.18.4. Spring XML

Spring XML의 동일한 예는 다음과 같습니다.

<bean id="mySlip" class="org.apache.camel.processor.DynamicRouterTest"/>

<camelContext xmlns="http://camel.apache.org/schema/spring">
    <route>
        <from uri="direct:start"/>
        <dynamicRouter>
            <!-- use a method call on a bean as dynamic router -->
            <method ref="mySlip" method="slip"/>
        </dynamicRouter>
    </route>

    <route>
        <from uri="direct:foo"/>
        <transform><constant>Bye World</constant></transform>
        <to uri="mock:foo"/>
    </route>

</camelContext>

8.18.5. 옵션

dynamicRouter DSL 명령은 다음 옵션을 지원합니다.

이름

기본값

설명

uriDelimiter

,

II 부. 라우팅 표현식 및 서술자 언어 에서 여러 끝점을 반환한 경우 사용되는 구분 기호입니다.

ignoreInvalidEndpoints

false

엔드포인트 uri를 확인할 수 없는 경우 무시해야 합니다. 그렇지 않으면 Camel에서 엔드포인트 uri가 유효하지 않음을 나타내는 예외가 throw됩니다.

1. @DynamicRouter 주석

@DynamicRouter 주석을 사용할 수도 있습니다. 예를 들면 다음과 같습니다.

// Java
public class MyDynamicRouter {

    @Consume(uri = "activemq:foo")
    @DynamicRouter
    public String route(@XPath("/customer/id") String customerId, @Header("Location") String location, Document body) {
        // query a database to find the best match of the endpoint based on the input parameteres
        // return the next endpoint uri, where to go. Return null to indicate the end.
    }
}

메시지가 슬립을 통해 진행됨에 따라 경로 메서드가 반복적으로 호출됩니다. 개념은 다음 대상의 끝점 URI를 반환하는 것입니다. 끝을 나타내는 null 을 반환합니다. 8.7절. “라우팅 슬립” 과 같이 여러 끝점을 반환할 수 있습니다. 여기서 각 끝점은 구분 기호로 구분됩니다.

9장. sa EIP

9.1. 개요

사가 EIP는 Camel 경로에서 일련의 관련 작업을 정의하는 방법을 제공하여 Camel 경로에 성공적으로 완료되거나 실행되지 않거나 보완할 수 있습니다. Privatega 구현은 전 세계적으로 일관된 결과로 모든 전송을 사용하여 통신하는 분산 서비스를 조정합니다. 사가 EIP는 다른 참여 서비스의 상태가 사가의 끝에만 일관성이 보장되고 중간 단계가 아닌 클래식 ACID 분산 (XA) 트랜잭션과 다릅니다.

saga EIP는 분산 트랜잭션 사용이 권장되지 않는 사용 사례에 적합합니다. 예를 들어, saga에 참여하는 서비스는 클래식 데이터베이스 또는 NoSQL 비 데이터 저장소와 같은 모든 종류의 데이터 저장소를 사용할 수 있습니다. 또한 서비스와 함께 트랜잭션 로그를 저장할 필요가 없으므로 상태 비저장 클라우드 서비스에서 사용하는 데 적합합니다. 또한 saga EIP는 트랜잭션과 다른 데이터베이스 수준 잠금을 사용하지 않기 때문에 약간의 시간 내에 완료할 필요가 없습니다. 따라서 몇 초에서 며칠까지 더 긴 기간 동안 지속될 수 있습니다.

sa EIP는 데이터에 대한 잠금을 사용하지 않습니다. 대신 이들은 흐름 실행 전에 존재하는 상태를 복원하기 위해 표준 흐름에 오류가 발생할 때 실행해야 하는 동작입니다. 조정 작업은 Java 또는 XML DSL을 사용하여 Camel 경로에 선언할 수 있으며 필요한 경우에만 Camel에서 호출할 수 있습니다(오류로 인해 saga가 취소되는 경우).

9.2. sa EIP 옵션

saga EIP는 아래 나열된 6 가지 옵션을 지원합니다.

이름설명Default유형

전파

sa 전파 모드(REQUIRED, REQUIRES_NEW, MANDATORY, SUPPORTS, NOT_SUPPORTED, NEVER)를 설정합니다.

필수 항목

SagaPropagation

completionMode

사가가 어떻게 완전한 것으로 간주되어야 하는지 결정합니다. AUTO 로 설정하면 saga를 시작하는 교환이 성공적으로 처리되거나 예외적으로 완료될 때 보완됩니다. MANUAL 로 설정하면 사용자는 saga:complete 또는 saga:compensate 엔드포인트를 사용하여 saga를 완료하거나 보완해야 합니다.

AUTO

SagaCompletionMode

timeoutInMilliseconds

saga의 최대 시간을 설정합니다. 시간 초과가 만료되면 saga가 자동으로 보완됩니다(다른 결정이 이루어지지 않은 경우).

 

long

Replacing

경로에서 수행된 모든 변경 사항을 보완하기 위해 호출되어야 하는 보수 끝점 URI입니다. 서비스 URI에 해당하는 경로는 보수를 수행하고 오류 없이 완료되어야 합니다. 보수 중에 오류가 발생하면 saga 서비스는 보수 URI를 다시 호출하여 재시도합니다.

 

SagaActionUriDefinition

완료

saga가 성공적으로 완료되면 호출되는 완료 끝점 URI입니다. 완료 URI에 해당하는 경로는 완료 작업을 수행하고 오류 없이 종료되어야 합니다. 완료 중에 오류가 발생하면sa 서비스가 완료 URI를 다시 호출하여 다시 시도합니다.

 

SagaActionUriDefinition

옵션

현재 교환의 속성을 저장하여 보수 또는 완료 콜백 경로에서 재사용할 수 있습니다. 예를 들어, 옵션은 일반적으로 권한 부여 작업에서 삭제된 개체의 식별자를 저장하고 검색하는 데 유용합니다. 옵션 값은 compensation/completion exchange의 입력 헤더로 변환됩니다.

 

list

9.3. saga 서비스 구성

saga EIP를 사용하려면 org.apache.camel.saga.CamelSagaService 인터페이스를 구현하는 서비스가 Camel 컨텍스트에 추가되어야 합니다. Camel은 현재 다음과 같은 SAga 서비스를 지원합니다.

  • InMemorySagaService: Secretga EIP의 기본 구현은 고급 기능(원격 컨텍스트 전파 없음, 애플리케이션 장애 시 일관성 보장 없음)을 지원하지 않습니다.

9.3.1. 메모리 내 사가 서비스 사용

SAga 상태의 지속성을 지원하지 않으므로 (메모리만 유지됨) 애플리케이션 장애 발생 시 사가 EIP의 일관성을 보장할 수 없기 때문에 프로덕션 환경에서 In-memory SAga 서비스는 권장되지 않습니다(예: JVM 충돌). 또한 메모리 내 SAga 서비스를 사용할 때 saga 컨텍스트를 전송 수준 헤더를 사용하여 원격 서비스로 전달할 수 없습니다(다른 구현으로 수행할 수 있음). 메모리 내 saga 서비스를 사용하려는 경우 다음 코드를 추가하여 Camel 컨텍스트를 사용자 지정할 수 있습니다. 서비스는 camel-core 모듈에 속합니다.

context.addService(new org.apache.camel.impl.saga.InMemorySagaService());

9.4. 예

예를 들어, 새 주문을 배치하고, 시스템에 두 개의 고유한 서비스(명령을 관리하는 방법과 신용을 관리하는 서비스)가 있습니다. 논리적으로는 충분한 크레딧이 있는 경우 주문을 할 수 있습니다. saga EIP를 사용하면 direct:buy 경로를 두 가지 고유한 작업으로 구성된 saga로 모델링할 수 있습니다. 하나는 순서를 만들고 신용을 취할 것입니다. 두 작업을 모두 실행하거나 신용없이 주문한 주문 중 어느 것도 일관되지 않은 결과 (주문없이 지불)로 간주 될 수 없습니다.

from("direct:buy")
  .saga()
    .to("direct:newOrder")
    .to("direct:reserveCredit");

나머지 예제에는 구매 동작이 변경되지 않습니다. 새 주문 및 예약 credit 작업을 모델링하는 데 사용되는 다양한 옵션은 다음과 같습니다.

from("direct:newOrder")
  .saga()
  .propagation(SagaPropagation.MANDATORY)
  .compensation("direct:cancelOrder")
    .transform().header(Exchange.SAGA_LONG_RUNNING_ACTION)
    .bean(orderManagerService, "newOrder")
    .log("Order ${body} created");

여기서 전파 모드는 MANDATORY 로 설정되어 있습니다. 즉, 이 경로의 모든 교환 흐름이 이미 saga의 일부여야 한다는 것을 의미합니다(사이크가 직접:buy 경로에서 생성되기 때문에 이 예제의 경우). direct:newOrder 경로는 saga가 취소되는 경우 순서를 취소할 책임이 있는 direct:cancelOrder 라는 보완 조치를 선언합니다.

각 교환에는 항상 여기에서 주문 ID로 사용되는 Exchange.SAGA_LONG_RUNNING_ACTION 헤더가 포함되어 있습니다. 이는 해당 조정 작업에서 삭제할 순서를 식별하지만 필수 사항은 아닙니다(옵션을 대체 솔루션으로 사용할 수 있음). 직접:newOrder 의 조정 작업은 직접:cancelOrder 이며 다음과 같습니다.

from("direct:cancelOrder")
  .transform().header(Exchange.SAGA_LONG_RUNNING_ACTION)
  .bean(orderManagerService, "cancelOrder")
  .log("Order ${body} cancelled");

사가 EIP 구현에 의해 주문이 취소되어야 할 때 자동으로 호출됩니다. 오류와 함께 종료되지 않습니다. direct:cancelOrder 경로에서 오류가 발생한 경우 EIP 구현은 특정 제한까지 조정 작업을 실행하기 위해 주기적으로 재시도해야 합니다. 즉, 조정 작업은 멱등이어야 하므로 여러 번 트리거될 수 있으며 어떤 경우에도 실패하지 않아야 합니다. 모든 재시도 후 보수를 수행할 수 없는 경우 saga 구현을 통해 수동 개입 프로세스를 트리거해야 합니다.

참고

직접:newOrder 경로의 실행 지연으로 인해 saga는 다른 당사자가 그 동안 다른 당사자에 의해 취소됩니다 (병렬 경로의 오류 또는 사파르 수준의 시간 초과로 인해 발생할 수 있습니다). 따라서 강제 조치 direct:cancelOrder 가 호출되면 취소된 주문 레코드를 찾을 수 없습니다. 완전한 글로벌 일관성을 보장하기 위해서는 모든 주요 조치와 해당 조정 작업은 예를 들어 주 동작이 동일해야합니다.

변경 동작을 사용할 수 없는 또 다른 접근 방식은 기본 작업으로 생성된 데이터가 발견되거나 최대 재시도 횟수가 소진될 때까지 지속적으로 보완적인 조치에 실패하는 것입니다. 이 접근 방식은 많은 상황에서 작동할 수 있지만 추론 적입니다.

신용 서비스는 주문 서비스와 거의 동일한 방식으로 구현됩니다.

from("direct:reserveCredit")
  .saga()
  .propagation(SagaPropagation.MANDATORY)
  .compensation("direct:refundCredit")
    .transform().header(Exchange.SAGA_LONG_RUNNING_ACTION)
    .bean(creditService, "reserveCredit")
    .log("Credit ${header.amount} reserved in action ${body}");

보수 조치에 대한 전화:

from("direct:refundCredit")
  .transform().header(Exchange.SAGA_LONG_RUNNING_ACTION)
  .bean(creditService, "refundCredit")
  .log("Credit for action ${body} refunded");

여기에서 신용 예약에 대한 보완 조치는 취소입니다.

9.4.1. 완료 이벤트 처리

saga가 완료되면 일부 유형의 처리가 필요합니다. 보수 끝점은 문제가 발생하여 saga가 취소될 때 호출됩니다. saga가 성공적으로 완료되면 완료 끝점 을 호출하여 추가 처리를 수행할 수 있습니다. 예를 들어 위의 주문 서비스에서 실제로 주문 준비를 시작하기 위해 주문이 완료되는 시점과 예약된 신용을 알아야 할 수 있습니다. 결제가 완료되지 않은 경우 주문 준비를 시작하지 않는 것이 좋습니다(읽기 권한을 보장하기 전에 예약된 메모리에 대한 액세스 권한을 부여하는 최신 CPU와 달리). 이 작업은 수정된 direct:newOrder 끝점으로 쉽게 수행할 수 있습니다.

  1. completeion 끝점을 호출합니다.
from("direct:newOrder")
  .saga()
  .propagation(SagaPropagation.MANDATORY)
  .compensation("direct:cancelOrder")
  .completion("direct:completeOrder")
    .transform().header(Exchange.SAGA_LONG_RUNNING_ACTION)
    .bean(orderManagerService, "newOrder")
    .log("Order ${body} created");
  1. direct:cancelOrder 는 이전 예와 동일합니다. 다음과 같이 성공적인 완료를 호출합니다.
from("direct:completeOrder")
  .transform().header(Exchange.SAGA_LONG_RUNNING_ACTION)
  .bean(orderManagerService, "findExternalId")
  .to("jms:prepareOrder")
  .log("Order ${body} sent for preparation");

saga가 완료되면 준비를 위해 명령이 JMS 큐로 전송됩니다. 조정 동작과 마찬가지로 완료 작업은 사가 코디네이터(특히 네트워크 오류와 같은 오류의 경우)에 의해 여러 번 호출될 수 있습니다. 이 예에서 prepareOrder JMS 큐를 수신하는 서비스는 가능한 중복을 보유할 준비가 되었습니다(복제 처리 방법에 대한 예제는 Idempotent Consumer EIP 참조).

9.4.2. 사용자 정의 식별자 및 옵션 사용

sa 옵션을 사용하여 사용자 정의 식별자를 등록할 수 있습니다. 예를 들어, 신용 서비스는 다음과 같이 리팩터링됩니다.

  1. 사용자 지정 ID를 생성하고 다음과 같이 본문에 설정합니다.
from("direct:reserveCredit")
  .bean(idService, "generateCustomId")
  .to("direct:creditReservation")
  1. 위임 작업을 수행하고 조정 작업에 필요한 대로 현재 본문을 표시합니다.
from("direct:creditReservation")
  .saga()
  .propagation(SagaPropagation.SUPPORTS)
  .option("CreditId", body())
  .compensation("direct:creditRefund")
    .bean(creditService, "reserveCredit")
    .log("Credit ${header.amount} reserved. Custom Id used is ${body}");
  1. saga가 취소된 경우에만 헤더에서 creditId 옵션을 검색합니다.
from("direct:creditRefund")
  .transform(header("CreditId")) // retrieve the CreditId option from headers
  .bean(creditService, "refundCredit")
  .log("Credit for Custom Id ${body} refunded");

direct:creditReservation 엔드포인트는 사도 외부에서 호출할 수 있으며, 전파 모드를 SUPPORTS 로 설정하면 됩니다. 이렇게 하면 사가 경로에 여러 옵션을 선언할 수 있습니다.

9.4.3. 시간 초과 설정

saga EIPs에서 시간 초과를 설정하면 시스템 오류 발생 시 saga가 영구적으로 유지되지 않습니다. saga EIP 구현에는 명시적으로 지정하지 않는 모든saga EIP에 설정된 기본 시간 초과가 있습니다. 시간 제한이 만료되면, 사가 EIP는 이전에 다른 결정을하지 않는 한 사가 (모든 참가자를 보완함)를 취소하기 로 결정합니다.

saga 참가자에 시간 초과는 다음과 같이 설정할 수 있습니다.

from("direct:newOrder")
  .saga()
  .timeout(1, TimeUnit.MINUTES) // newOrder requires that the saga is completed within 1 minute
  .propagation(SagaPropagation.MANDATORY)
  .compensation("direct:cancelOrder")
  .completion("direct:completeOrder")
    // ...
    .log("Order ${body} created");

모든 참가자(예: 신용 서비스, 주문 서비스)는 자체 시간 초과를 설정할 수 있습니다. 이러한 시간 초과의 최소 값은 함께 구성될 때 saga의 시간 초과 값으로 사용됩니다. 시간 초과는 다음과 같이 사가 수준에서 지정할 수도 있습니다.

from("direct:buy")
  .saga()
  .timeout(5, TimeUnit.MINUTES) // timeout at saga level
    .to("direct:newOrder")
    .to("direct:reserveCredit");

9.4.4. 전파 선택

위의 예제에서는 MANDATORYSUPPORTS 전파 모드뿐만 아니라 REQUIRED 전파 모드, 즉 다른 항목이 지정되지 않을 때 사용되는 기본 전파 모드를 사용했습니다. 이러한 전파 모드는 1:1 트랜잭션 컨텍스트에서 사용되는 동등한 모드를 매핑합니다.

전파설명

REQUIRED

기존sa에 가입하거나 존재하지 않는 경우 새 사가를 만듭니다.

REQUIRES_NEW

항상 새 사가를 만듭니다. 이전 사가를 일시 중지한 후 새 서비스가 종료되면 다시 시작합니다.

필수

사도는 이미 존재하고 있어야 합니다. 기존의 saga가 결합됩니다.

SUPPORTS

사가가 이미 존재하는 경우, 여기에 가입하십시오.

NOT_SUPPORTED

saga가 이미 존재하는 경우 현재 블록이 완료되면 일시 중지되고 재개됩니다.

NEVER

현재 블록은 saga 내에서 호출해서는 안 됩니다.

9.4.5. 수동 완료(Advanced) 사용

사가가 모두 동기적으로 실행될 수는 없지만, 예를 들어 비동기식 통신 채널을 사용하는 외부 서비스와의 통신이 필요한 경우,acga는 해당 채널을 생성하는 교환이 완료될 때 완료 모드를 AUTO (기본값)로 설정할 수 없기 때문입니다. 이는 종종 장기 실행 시간 (시간, 일)이 있는 사가 EIP의 경우입니다. 이러한 경우 MANUAL 완료 모드를 사용해야 합니다.

from("direct:mysaga")
  .saga()
  .completionMode(SagaCompletionMode.MANUAL)
  .completion("direct:finalize")
  .timeout(2, TimeUnit.HOURS)
    .to("seda:newOrder")
    .to("seda:reserveCredit");

seda:newOrder 및 seda:reserveCredit에 대한 비동기 처리를 추가합니다. 비동기 콜백을 seda:operationCompleted로 보냅니다.

from("seda:operationCompleted") // an asynchronous callback
  .saga()
  .propagation(SagaPropagation.MANDATORY)
    .bean(controlService, "actionExecuted")
    .choice()
      .when(body().isEqualTo("ok"))
        .to("saga:complete") // complete the current saga manually (saga component)
    .end()

direct:finalize 엔드포인트를 추가하여 최종 작업을 실행할 수 있습니다.

완료 모드를 MANUAL 로 설정하면 경로 direct:mysaga 에서 교환이 처리될 때 saga가 완료되지 않지만 더 오래 지속됩니다(최대 기간은 2시간으로 설정됨). 두 비동기 작업이 모두 완료되면sa가 완료됩니다. Camel saga Component의 saga:complete 엔드포인트를 사용하여 완료되는 호출이 수행됩니다. saga:compensate)를 수동으로 보완하기 위한 유사한 엔드포인트가 있습니다.

9.5. XML 구성

saga 기능은 XML 구성을 사용하려는 사용자가 사용할 수 있습니다. 다음 스니펫에서는 예를 보여줍니다.

<route>
  <from uri="direct:start"/>
  <saga>
    <compensation uri="direct:compensation" />
    <completion uri="direct:completion" />
    <option optionName="myOptionKey">
      <constant>myOptionValue</constant>
    </option>
    <option optionName="myOptionKey2">
      <constant>myOptionValue2</constant>
    </option>
  </saga>
  <to uri="direct:action1" />
  <to uri="direct:action2" />
</route>

10장. 메시지 Cryostat

초록

메시지 변환 패턴은 다양한 용도로 메시지 내용을 수정하는 방법을 설명합니다.

10.1. 콘텐츠 Enricher

10.1.1. 개요

콘텐츠 강화 패턴은 메시지 대상에 원본 메시지에 있는 것보다 더 많은 데이터가 필요한 시나리오를 설명합니다. 이 경우 메시지 번역자, 라우팅 논리의 임의의 프로세서 또는 컨텐츠 강화 방법을 사용하여 외부 리소스에서 추가 데이터를 가져올 수 있습니다.

그림 10.1. Content Enricher Pattern

콘텐츠 강화 패턴

10.1.2. 콘텐츠 강화를 위한 대안

Apache Camel은 콘텐츠를 보강하는 여러 가지 방법을 지원합니다.

  • 라우팅 논리에서 임의의 프로세서가 있는 메시지 번역
  • enrich() 메서드는 현재 교환의 사본을 생산자 엔드 포인트로 보낸 다음 결과 응답의 데이터를 사용하여 리소스에서 추가 데이터를 가져옵니다. 부자에 의해 생성된 교환은 항상 InOut 교환입니다.
  • pollEnrich() 메서드는 데이터를 위해 소비자 엔드포인트를 폴링하여 추가 데이터를 가져옵니다. 효과적으로, 메인 경로의 소비자 끝점과 pollEnrich() 작업의 소비자 끝점이 결합됩니다. 즉, 경로의 초기 소비자에 대한 수신 메시지는 소비자의 pollEnrich() 메서드를 폴링합니다.
참고

enrich()pollEnrich() 메서드는 동적 엔드포인트 URI를 지원합니다. 현재 교환에서 값을 가져올 수 있는 식을 지정하여 URI를 계산할 수 있습니다. 예를 들어 데이터 교환에서 계산된 이름으로 파일을 폴링할 수 있습니다. 이 동작은 Camel 2.16에서 도입되었습니다. 이 변경으로 인해 XML DSL이 중단되고 쉽게 마이그레이션할 수 있습니다. Java DSL은 이전 버전과 호환됩니다.

10.1.3. 메시지 번역가 및 프로세서를 사용하여 컨텐츠 강화

Camel은 스마트 완료를 제공하고 리팩토링 보안을 유지하는 유형 안전 IDE 친화적인 방법을 사용하여 라우팅 및 중재 규칙을 생성할 수 있는 유창한 빌더 를 제공합니다. 분산 시스템을 테스트할 때 특정 시스템을 사용하거나 작성할 때까지 시스템의 다른 부분을 테스트할 수 있도록 특정 외부 시스템을 스텁해야 합니다. 이를 수행하는 한 가지 방법은 대부분 정적인 본문이 있는 동적 메시지를 생성하여 요청에 대한 응답을 생성하는 일종의 템플릿 시스템을 사용하는 것입니다. 템플릿을 사용하는 또 다른 방법은 한 대상의 메시지를 사용하여 Velocity 또는 XQuery 와 같은 것으로 변환한 다음 다른 대상으로 전송하는 것입니다. 다음 예제에서는 InOnly (한 가지 방법) 메시지에 대해 이를 보여줍니다.

from("activemq:My.Queue").
  to("velocity:com/acme/MyResponse.vm").
  to("activemq:Another.Queue");

InOut (request-reply) 메시징을 사용하여 ActiveMQ의 My.Queue 큐에서 요청을 처리한다고 가정합니다. JMSReplyTo 대상으로 이동하는 템플릿 생성 응답이 필요합니다. 다음 예제에서는 이 작업을 수행하는 방법을 보여줍니다.

from("activemq:My.Queue").
  to("velocity:com/acme/MyResponse.vm");

다음 간단한 예제에서는 DSL을 사용하여 메시지 본문을 변환하는 방법을 보여줍니다.

from("direct:start").setBody(body().append(" World!")).to("mock:result");

다음 예제에서는 명시적 Java 코드를 사용하여 프로세서를 추가합니다.

from("direct:start").process(new Processor() {
    public void process(Exchange exchange) {
        Message in = exchange.getIn();
        in.setBody(in.getBody(String.class) + " World!");
    }
}).to("mock:result");

다음 예제에서는 useful integration을 사용하여 빈을 사용하여 transformer 역할을 할 수 있습니다.

from("activemq:My.Queue").
  beanRef("myBeanName", "myMethodName").
  to("activemq:Another.Queue");

다음 예제에서는 Spring XML 구현을 보여줍니다.

<route>
  <from uri="activemq:Input"/>
  <bean ref="myBeanName" method="doTransform"/>
  <to uri="activemq:Output"/>
</route>/>

10.1.4. enrich() 메서드를 사용하여 콘텐츠를 강화

AggregationStrategy aggregationStrategy = ...

from("direct:start")
  .enrich("direct:resource", aggregationStrategy)
  .to("direct:result");

from("direct:resource")
...

컨텐츠 강화(신분)는 들어오는 메시지(복원 교환포함)를 강화하기 위해 리소스 끝점 에서 추가 데이터를 검색합니다. 집계 전략은 원래 교환과 리소스 교환을 결합합니다. 집계Strategy.aggregate(Exchange, Exchange) 메서드의 첫 번째 매개 변수는 원래 교환에 해당하고 두 번째 매개 변수는 리소스 교환에 해당합니다. 리소스 끝점의 결과는 리소스 교환의 Out 메시지에 저장됩니다. 다음은 자체 집계 전략 클래스를 구현하기 위한 샘플 템플릿입니다.

public class ExampleAggregationStrategy implements AggregationStrategy {

    public Exchange aggregate(Exchange original, Exchange resource) {
        Object originalBody = original.getIn().getBody();
        Object resourceResponse = resource.getOut().getBody();
        Object mergeResult = ... // combine original body and resource response
        if (original.getPattern().isOutCapable()) {
            original.getOut().setBody(mergeResult);
        } else {
            original.getIn().setBody(mergeResult);
        }
        return original;
    }

}

이 템플릿을 사용하면 원래 교환에 모든 교환 패턴이 있을 수 있습니다. 번영자에 의해 생성되는 리소스 교환은 항상 InOut 교환입니다.

10.1.5. Spring XML 강화 예

위 예제는 Spring XML에서도 구현할 수 있습니다.

<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
  <route>
    <from uri="direct:start"/>
    <enrich strategyRef="aggregationStrategy">
      <constant>direct:resource</constant>
    <to uri="direct:result"/>
  </route>
  <route>
    <from uri="direct:resource"/>
    ...
  </route>
</camelContext>
 <bean id="aggregationStrategy" class="..." />

10.1.6. 콘텐츠를 보강할 때 기본 집계 전략

집계 전략은 선택 사항입니다. 이를 제공하지 않으면 Apache Camel에서 기본적으로 리소스에서 얻은 본문을 사용합니다. 예를 들면 다음과 같습니다.

from("direct:start")
  .enrich("direct:resource")
  .to("direct:result");

이전 경로에서 direct:result 엔드포인트로 전송된 메시지에는 direct:resource 의 출력이 포함되어 있습니다. 이 예제에서는 사용자 지정 집계를 사용하지 않기 때문입니다.

XML DSL에서 다음과 같이 strategyRef 특성을 생략합니다.

<route>
    <from uri="direct:start"/>
    <enrich uri="direct:resource"/>
    <to uri="direct:result"/>
</route>

10.1.7. enrich() 메서드에서 지원하는 옵션

강력한 DSL 명령은 다음 옵션을 지원합니다.

이름

기본값

설명

expression

없음

Camel 2.16부터 이 옵션이 필요합니다. 에서 보강할 외부 서비스의 URI를 구성하기 위한 표현식을 지정합니다. 단순 표현식 언어, Constant 표현식 언어 또는 현재 교환의 값에서 동적으로 URI를 계산할 수 있는 기타 언어를 사용할 수 있습니다.

uri

 

이러한 옵션이 제거되었습니다. 대신 expression 옵션을 지정합니다. Camel 2.15 및 이전 버전에서는 uri 옵션 또는 ref 옵션 사양이 필요했습니다. 각 옵션은 외부 서비스에서 보강할 끝점 URI를 지정했습니다.

ref

 

에서 보강할 외부 서비스의 끝점을 나타냅니다. uri 또는 ref 중 하나를 사용해야 합니다.

strategyRef

 

외부 서비스의 응답을 단일 발신 메시지로 병합하는 데 사용되는 집계Strategy 를 나타냅니다. 기본적으로 Camel은 외부 서비스의 응답을 발신 메시지로 사용합니다. Cryostat를 AggregationStrategy 로 사용할 수 있습니다. 자세한 내용은 집계 패턴 설명서를 참조하십시오.

strategyMethodName

 

Cryostat를 AggregationStrategy 로 사용하는 경우 이 옵션을 지정하여 집계 메서드의 이름을 명시적으로 선언합니다. 자세한 내용은 집계 패턴을 참조하십시오.

strategyMethodAllowNull

false

기본 동작은 집계 메서드가 보강할 데이터가 없는 경우 사용되지 않는다는 것입니다. 이 옵션이 true이면 보강할 데이터가 없고 AggregationStrategy 로 Cryostat를 사용하는 경우 null 값이 oldExchange 로 사용됩니다. 자세한 내용은 집계 패턴을 참조하십시오.

aggregateOnException

false

리소스에서 보강하기 위해 데이터를 검색하는 동안 예외가 발생한 경우 기본 동작은 집계 메서드가 사용되지 않는다는 것입니다. 이 옵션을 true 로 설정하면 최종 사용자가 집계 메서드에 예외가 있는 경우 수행할 작업을 제어할 수 있습니다. 예를 들어 예외를 억제하거나 사용자 정의 메시지 본문을 설정할 수 있습니다.

shareUntOfWork

false

Camel 2.16부터는 기본 동작은 보강 작업이 부모 교환과 리소스 교환 간에 작업 단위를 공유하지 않는다는 것입니다. 즉, 리소스 교환에는 자체 개별 작업 단위가 있습니다. 자세한 내용은 Splitter 패턴 설명서를 참조하십시오.

cacheSize

1000

Camel 2.16부터는 ProducerCache 의 캐시 크기를 구성하려면 이 옵션을 지정하여 보강 작업에서 재사용할 수 있도록 생산자를 캐시합니다. 이 캐시를 끄려면 cacheSize 옵션을 -1 로 설정합니다.

ignoreInvalidEndpoint

false

Camel 2.16부터 이 옵션은 해결할 수 없는 엔드포인트 URI를 무시할지 여부를 나타냅니다. 기본 동작은 Camel이 잘못된 엔드포인트 URI를 식별하는 예외를 throw한다는 것입니다.

10.1.8. enrich() 메서드를 사용할 때 집계 전략 지정

enrich() 메서드는 리소스 끝점에서 추가 데이터를 검색하여 원래 교환에 포함된 들어오는 메시지를 보강합니다. 집계 전략을 사용하여 원래 교환과 리소스 교환을 결합할 수 있습니다. 집계Strategy.aggregate(Exchange, 교환) 방법의 첫 번째 매개변수는 원래 교환에 해당합니다. 두 번째 매개 변수는 리소스 교환에 해당합니다. 리소스 끝점의 결과는 리소스 교환의 Out 메시지에 저장됩니다. 예를 들면 다음과 같습니다.

AggregationStrategy aggregationStrategy = ...

   from("direct:start")
   .enrich("direct:resource", aggregationStrategy)
   .to("direct:result");

   from("direct:resource")
...

다음 코드는 집계 전략을 구현하기 위한 템플릿입니다. 이 템플릿을 사용하는 구현에서는 원래 교환이 모든 메시지 교환 패턴일 수 있습니다. 번영자에 의해 생성되는 리소스 교환은 항상 InOut 메시지 교환 패턴입니다.

public class ExampleAggregationStrategy implements AggregationStrategy {

    public Exchange aggregate(Exchange original, Exchange resource) {
        Object originalBody = original.getIn().getBody();
        Object resourceResponse = resource.getIn().getBody();
        Object mergeResult = ... // combine original body and resource response
        if (original.getPattern().isOutCapable()) {
            original.getOut().setBody(mergeResult);
        } else {
            original.getIn().setBody(mergeResult);
        }
        return original;
    }

}

다음 예제에서는 Spring XML DSL을 사용하여 집계 전략을 구현하는 방법을 보여줍니다.

<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
  <route>
    <from uri="direct:start"/>
    <enrich strategyRef="aggregationStrategy">
      <constant>direct:resource</constant>
    </enrich>
    <to uri="direct:result"/>
  </route>
  <route>
    <from uri="direct:resource"/>
    ...
  </route>
</camelContext>

<bean id="aggregationStrategy" class="..." />

10.1.9. enrich()를 사용하여 동적 URI 사용

Camel 2.16부터 enrich()pollEnrich() 메서드는 현재 교환의 정보를 기반으로 계산되는 동적 URI 사용을 지원합니다. 예를 들어 orderId 키가 있는 헤더가 HTTP URL의 콘텐츠 경로의 일부로 사용되는 HTTP 끝점에서 강화하려면 다음과 같은 작업을 수행할 수 있습니다.

from("direct:start")
  .enrich().simple("http:myserver/${header.orderId}/order")
  .to("direct:result");

다음은 XML DSL의 예는 다음과 같습니다.

<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
<route>
   <from uri="direct:start"/>
   <enrich>
      <simple>http:myserver/${header.orderId}/order</simple>
   </enrich>
   <to uri="direct:result"/>
</route>

10.1.10. pollEnrich() 메서드를 사용하여 콘텐츠를 강화

pollEnrich 명령은 리소스 끝점을 소비자 로 처리합니다. 리소스 엔드포인트로 교환을 보내는 대신 엔드포인트를 폴링 합니다. 리소스 끝점에서 사용할 수 있는 교환이 없는 경우 기본적으로 폴링은 즉시 반환됩니다. 예를 들어 다음 경로는 들어오는 JMS 메시지의 헤더에서 이름이 추출된 파일을 읽습니다.

from("activemq:queue:order")
   .pollEnrich("file://order/data/additional?fileName=orderId")
   .to("bean:processOrder");

파일이 준비될 때까지 대기할 시간을 제한할 수 있습니다. 다음 예제에서는 최대 20초 대기를 보여줍니다.

from("activemq:queue:order")
   .pollEnrich("file://order/data/additional?fileName=orderId", 20000) // timeout is in milliseconds
   .to("bean:processOrder");

pollEnrich() 에 대한 집계 전략을 지정할 수도 있습니다. 예를 들면 다음과 같습니다.

   .pollEnrich("file://order/data/additional?fileName=orderId", 20000, aggregationStrategy)

pollEnrich() 메서드는 consumer.bridgeErrorHandler=true 로 구성된 소비자를 지원합니다. 이를 통해 경로 오류 처리기에 전파되는 폴링의 예외가 있어 폴링을 다시 시도할 수 있습니다.

참고

consumer.bridgeErrorHandler=true 에 대한 지원은 Camel 2.18의 새로운 기능입니다. 이 동작은 Camel 2.17에서 지원되지 않습니다.

집계 전략의 aggregate() 메서드에 전달된 리소스 교환은 교환이 수신되기 전에 폴링이 시간 초과되면 null 일 수 있습니다.

10.1.11. pollEnrich()에서 사용하는 폴링 방법

pollEnrich() 메서드는 다음 폴링 방법 중 하나를 호출하여 소비자 끝점을 폴링합니다.

  • receiveNoWait()(기본값입니다.)
  • receive()
  • receive(긴 시간)

pollEnrich() 명령의 시간 초과 인수(밀리초 단위로 지정)는 다음과 같이 호출할 메서드를 결정합니다.

  • 시간 초과가 0 이거나 지정되지 않은 경우 pollEnrich() 호출은 11 Wait을 수신합니다.
  • 시간 제한이 음수이면 pollEnrich() 호출이 수신됩니다.
  • 그렇지 않으면 pollEnrich() 호출이 수신(timeout) 됩니다.

데이터가 없는 경우 집계 전략의 newExchange 는 null입니다.

10.1.12. pollEnrich() 메서드를 사용하는 예

다음 예제에서는 inbox/data.txt 파일에서 콘텐츠를 로드하여 메시지를 보강하는 방법을 보여줍니다.

 from("direct:start")
   .pollEnrich("file:inbox?fileName=data.txt")
   .to("direct:result");

다음은 XML DSL의 예는 다음과 같습니다.

<route>
   <from uri="direct:start"/>
   <pollEnrich>
      <constant>file:inbox?fileName=data.txt"</constant>
   </pollEnrich>
   <to uri="direct:result"/>
</route>

지정된 파일이 없으면 메시지가 비어 있습니다. 파일이 존재하거나 특정 시간까지 대기할 시간 초과를 지정할 수 있습니다. 다음 예에서 명령은 5초 이상 대기하지 않습니다.

<route>
   <from uri="direct:start"/>
   <pollEnrich timeout="5000">
      <constant>file:inbox?fileName=data.txt"</constant>
   </pollEnrich>
   <to uri="direct:result"/>
</route>

10.1.13. pollEnrich()와 함께 동적 URI 사용

Camel 2.16부터 enrich()pollEnrich() 메서드는 현재 교환의 정보를 기반으로 계산되는 동적 URI 사용을 지원합니다. 예를 들어, 헤더를 사용하여 SEDA 큐 이름을 나타내는 끝점에서 강력한 폴링을 수행하려면 다음과 같은 작업을 수행할 수 있습니다.

from("direct:start")
  .pollEnrich().simple("seda:${header.name}")
  .to("direct:result");

다음은 XML DSL의 예는 다음과 같습니다.

<route>
   <from uri="direct:start"/>
   <pollEnrich>
      <simple>seda${header.name}</simple>
   </pollEnrich>
   <to uri="direct:result"/>
</route>

10.1.14. pollEnrich() 메서드에서 지원하는 옵션

pollEnrich DSL 명령은 다음 옵션을 지원합니다.

이름

기본값

설명

expression

없음

Camel 2.16부터 이 옵션이 필요합니다. 에서 보강할 외부 서비스의 URI를 구성하기 위한 표현식을 지정합니다. 단순 표현식 언어, Constant 표현식 언어 또는 현재 교환의 값에서 동적으로 URI를 계산할 수 있는 기타 언어를 사용할 수 있습니다.

uri

 

이러한 옵션이 제거되었습니다. 대신 expression 옵션을 지정합니다. Camel 2.15 및 이전 버전에서는 uri 옵션 또는 ref 옵션 사양이 필요했습니다. 각 옵션은 외부 서비스에서 보강할 끝점 URI를 지정했습니다.

ref

 

에서 보강할 외부 서비스의 끝점을 나타냅니다. uri 또는 ref 중 하나를 사용해야 합니다.

strategyRef

 

외부 서비스의 응답을 단일 발신 메시지로 병합하는 데 사용되는 집계Strategy 를 나타냅니다. 기본적으로 Camel은 외부 서비스의 응답을 발신 메시지로 사용합니다. Cryostat를 AggregationStrategy 로 사용할 수 있습니다. 자세한 내용은 집계 패턴 설명서를 참조하십시오.

strategyMethodName

 

Cryostat를 AggregationStrategy 로 사용하는 경우 이 옵션을 지정하여 집계 메서드의 이름을 명시적으로 선언합니다. 자세한 내용은 집계 패턴을 참조하십시오.

strategyMethodAllowNull

false

기본 동작은 집계 메서드가 보강할 데이터가 없는 경우 사용되지 않는다는 것입니다. 이 옵션이 true이면 보강할 데이터가 없고 AggregationStrategy 로 Cryostat를 사용하는 경우 null 값이 oldExchange 로 사용됩니다. 자세한 내용은 집계 패턴을 참조하십시오.

timeout

-1

외부 서비스에서 폴링할 때 응답을 대기하는 최대 시간(밀리초)입니다. 기본 동작은 pollEnrich() 메서드가 receive() 메서드를 호출한다는 것입니다. receive() 는 메시지를 사용할 수 있을 때까지 차단할 수 있으므로 권장 사항은 항상 시간 초과를 지정하는 것입니다.

aggregateOnException

false

리소스에서 보강하기 위해 데이터를 검색하는 동안 예외가 발생한 경우 기본 동작은 집계 메서드가 사용되지 않는다는 것입니다. 이 옵션을 true 로 설정하면 최종 사용자가 집계 메서드에 예외가 있는 경우 수행할 작업을 제어할 수 있습니다. 예를 들어 예외를 억제하거나 사용자 정의 메시지 본문을 설정할 수 있습니다.

cacheSize

1000

pollEnrich() 작업에서 재사용할 소비자를 캐시하는 ConsumerCache 의 캐시 크기를 구성하려면 이 옵션을 지정합니다. 이 캐시를 끄려면 cacheSize 옵션을 -1 로 설정합니다.

ignoreInvalidEndpoint

false

확인할 수 없는 엔드포인트 URI를 무시할지 여부를 나타냅니다. 기본 동작은 Camel이 잘못된 엔드포인트 URI를 식별하는 예외를 throw한다는 것입니다.

10.2. 콘텐츠 필터

10.2.1. 개요

콘텐츠 필터 패턴은 의도한 수신자에 전달하기 전에 메시지에서 불필요한 콘텐츠를 필터링해야 하는 시나리오를 설명합니다. 예를 들어 콘텐츠 필터를 사용하여 메시지에서 기밀 정보를 제거할 수 있습니다.

그림 10.2. 콘텐츠 필터 패턴

콘텐츠 필터 패턴

메시지를 필터링하는 일반적인 방법은 지원되는 스크립팅 언어(예: XSLT, XQuery 또는 JoSQL) 중 하나로 작성된 DSL에서 표현식을 사용하는 것입니다.

10.2.2. 콘텐츠 필터 구현

콘텐츠 필터는 본질적으로 특정 목적을 위한 메시지 처리 기술을 적용하는 것입니다. 콘텐츠 필터를 구현하려면 다음과 같은 메시지 처리 기술을 사용할 수 있습니다.

10.2.3. XML 구성 예

다음 예제에서는 XML로 동일한 경로를 구성하는 방법을 보여줍니다.

<camelContext xmlns="http://camel.apache.org/schema/spring">
  <route>
    <from uri="activemq:My.Queue"/>
    <to uri="xslt:classpath:com/acme/content_filter.xsl"/>
    <to uri="activemq:Another.Queue"/>
  </route>
</camelContext>

10.2.4. Cryostat 필터 사용

Cryostat를 사용하여 관심 있는 메시지의 일부를 필터링할 수도 있습니다.

<route>
  <from uri="activemq:Input"/>
  <setBody><xpath resultType="org.w3c.dom.Document">//foo:bar</xpath></setBody>
  <to uri="activemq:Output"/>
</route>

10.3. 노멀라이저

10.3.1. 개요

노멀라이저 패턴은 의미 체계적으로 동일하지만 다른 형식으로 도달하는 메시지를 처리하는 데 사용됩니다. 노멀라이저는 들어오는 메시지를 공통 형식으로 변환합니다.

Apache Camel에서는 들어오는 메시지의 형식을 감지하는 8.1절. “콘텐츠 기반 라우터” 를 결합하여 다른 5.6절. “메시지#159” 로 들어오는 형식을 공통 형식으로 변환하는 컬렉션을 결합하여 노멀라이저 패턴을 구현할 수 있습니다.

그림 10.3. 노멀라이저 패턴

노멀라이저 패턴

10.3.2. Java DSL 예

이 예에서는 두 가지 유형의 XML 메시지를 공통 형식으로 변환하는 Message Normalizer를 보여줍니다. 그런 다음 이 공통 형식의 메시지가 필터링됩니다.

Fluent Builders사용

// we need to normalize two types of incoming messages
from("direct:start")
    .choice()
        .when().xpath("/employee").to("bean:normalizer?method=employeeToPerson")
        .when().xpath("/customer").to("bean:normalizer?method=customerToPerson")
    .end()
    .to("mock:result");

이 경우 Java 8080을 노멀라이저로 사용하고 있습니다. 클래스는 다음과 같습니다.

// Java
public class MyNormalizer {
    public void employeeToPerson(Exchange exchange, @XPath("/employee/name/text()") String name) {
        exchange.getOut().setBody(createPerson(name));
    }

    public void customerToPerson(Exchange exchange, @XPath("/customer/@name") String name) {
        exchange.getOut().setBody(createPerson(name));
    }

    private String createPerson(String name) {
        return "<person name=\"" + name + "\"/>";
    }
}

10.3.3. XML 구성 예

XML DSL의 동일한 예

<camelContext xmlns="http://camel.apache.org/schema/spring">
  <route>
    <from uri="direct:start"/>
    <choice>
      <when>
        <xpath>/employee</xpath>
        <to uri="bean:normalizer?method=employeeToPerson"/>
      </when>
      <when>
        <xpath>/customer</xpath>
        <to uri="bean:normalizer?method=customerToPerson"/>
      </when>
    </choice>
    <to uri="mock:result"/>
  </route>
</camelContext>

<bean id="normalizer" class="org.apache.camel.processor.MyNormalizer"/>

10.4. 클레임 확인 EIP

10.4.1. 클레임 확인 EIP

그림 10.4. “클레임 검사 패턴” 에 표시된 클레임 검사 EIP 패턴을 사용하면 메시지 콘텐츠를 클레임 검사(별도 키)로 교체할 수 있습니다. 클레임 검사 EIP 패턴을 사용하여 나중에 메시지 콘텐츠를 검색합니다. 메시지 콘텐츠를 데이터베이스 또는 파일 시스템과 같은 영구 저장소에 일시적으로 저장할 수 있습니다. 이 패턴은 메시지 콘텐츠가 매우 크며 모든 구성 요소에 모든 정보가 필요한 것은 아닙니다.

외부 당사자와의 정보를 신뢰할 수 없는 경우에도 유용할 수 있습니다. 이 경우 클레임 검사를 사용하여 데이터의 중요한 부분을 숨깁니다.

EIP 패턴의 Camel 구현은 메시지 콘텐츠를 내부 메모리 저장소에 일시적으로 저장합니다.

그림 10.4. 클레임 검사 패턴

라이브러리에 저장

10.4.1. 클레임 검사 EIP 옵션

클레임 검사 EIP는 다음 표에 나열된 옵션을 지원합니다.

이름

설명

Default

유형

작업

클레임 검사 작업을 사용해야 합니다. 다음 작업을 지원합니다.

get - 지정된 키에 의한 클레임 검사를(제거하지 않음) 가져옵니다.

GetAndRemove - 지정된 키에 의해 클레임 검사를 가져오고 제거합니다.

* set - 지정된 키를 사용하여 새 클레임 검사를 설정합니다. 키가 이미 있으면 재정의됩니다.

* push - 스택에 새 클레임 검사를 설정합니다(키를 사용하지 않음).

* pop - 스택에서 최신 클레임 검사를 가져옵니다(키를 사용하지 않음).

Get , Get AndRemove 또는 Set 작업을 사용하는 경우 키를 지정해야 합니다. 그런 다음 이러한 작업은 키를 사용하여 데이터를 저장하고 검색합니다. 이러한 작업을 사용하여 여러 데이터를 다른 키에 저장합니다. 그러나 푸시팝업 작업에서는 키를 사용하지 않고 스택 구조에 데이터를 저장합니다.

 

ClaimCheckOperation

key

클레임 확인에 특정 키를 사용하려면 다음을 수행합니다.

 

문자열

filter

클레임 검사 리포지토리에서 다시 병합할 데이터를 제어하는 필터를 지정합니다.

 

문자열

strategyRef

기본 구현 대신 사용자 정의 집계Strategy 를 사용하려면 다음을 수행합니다. 사용자 정의 집계 전략을 모두 사용하고 동시에 데이터를 구성할 수 없습니다.

 

문자열

10.4.2. 필터 옵션

Filter 옵션을 사용하여 Get 또는 Pop 작업을 사용할 때 병합할 데이터를 정의합니다. AggregationStrategy 를 사용하여 데이터를 다시 병합합니다. 기본 전략에서는 filter 옵션을 사용하여 병합할 데이터를 쉽게 지정합니다.

filter 옵션은 다음 구문으로 String 값을 사용합니다.

  • body: 메시지 본문을 집계하려면
  • attachments: 모든 메시지 첨부 파일을 집계하려면
  • headers: 모든 메시지 헤더를 집계하기 위해
  • header:pattern: 패턴과 일치하는 모든 메시지 헤더를 집계합니다.

패턴 규칙은 와일드카드 및 정규식을 지원합니다.

  • 와일드카드 일치(패턴은 * 로 끝나고 이름은 패턴으로 시작)
  • 정규 표현식 일치

여러 규칙을 지정하려면 쉼표 (,)로 구분합니다.

다음은 foo 로 시작하는 메시지 본문 및 모든 헤더를 포함하는 기본 필터 예제입니다.

body, header:foo*
  • 메시지 본문만 병합하려면 body
  • 메시지 첨부 파일만 병합하려면 다음을 수행합니다.
  • 헤더만 병합하려면 헤더만 병합
  • 헤더 이름 foo only: header:foo를 병합하려면 다음을 수행합니다.

필터 규칙을 비어 있거나 와일드카드로 지정하는 경우 모든 항목을 병합할 수 있습니다. 자세한 내용은 병합할 데이터 필터링을 참조하십시오.

참고

데이터를 다시 병합하면 시스템은 기존 데이터를 덮어씁니다. 또한 기존 데이터를 저장합니다.

10.4.2. 포함 및 제외 패턴을 사용하여 필터 옵션

다음은 include,exclude 또는 remove 옵션을 지정하는 데 사용할 수 있는 접두사를 지원하는 구문입니다.

  • + : 포함하기 (기본 모드임)
  • - : 제외하려면 (포함하는 것보다 우선합니다)
  • -- : 제거(제거)

예를 들면 다음과 같습니다.

  • 메시지 본문을 건너뛰고 다른 모든 것을 병합하려면 -body를 사용합니다.
  • 메시지 헤더 foo 를 건너뛰고 다른 모든 것을 병합하려면 -header:foo를 사용합니다.

데이터를 병합할 때 헤더를 제거하도록 시스템에 지시할 수도 있습니다. 예를 들어 bar로 시작하는 모든 헤더를 제거하려면 --headers:bar* 를 사용합니다.

참고

include(+)와 exclude(-) header:pattern 을 동시에 사용하지 마십시오.

10.4.3. Java 예

다음 예제에서는 PushPop 작업 작동을 보여 줍니다.The following example shows the Push and pop operations in action:

from("direct:start")
    .to("mock:a")
    .claimCheck(ClaimCheckOperation.Push)
    .transform().constant("Bye World")
    .to("mock:b")
    .claimCheck(ClaimCheckOperation.Pop)
    .to("mock:c");

다음은 GetSet 작업을 사용하는 예입니다. 예에서는 foo 키를 사용합니다.

from("direct:start")
    .to("mock:a")
    .claimCheck(ClaimCheckOperation.Set, "foo")
    .transform().constant("Bye World")
    .to("mock:b")
    .claimCheck(ClaimCheckOperation.Get, "foo")
    .to("mock:c")
    .transform().constant("Hi World")
    .to("mock:d")
    .claimCheck(ClaimCheckOperation.Get, "foo")
    .to("mock:e");
참고

데이터를 제거하지 않기 때문에 Get 작업을 사용하여 동일한 데이터를 두 번 가져올 수 있습니다. 그러나 데이터를 한 번만 가져오려면 GetAndRemove 작업을 사용합니다.

다음 예제에서는 foo 또는 bar 로 헤더만 반환하려는 filter 옵션을 사용하는 방법을 보여줍니다.

from("direct:start")
    .to("mock:a")
    .claimCheck(ClaimCheckOperation.Push)
    .transform().constant("Bye World")
    .setHeader("foo", constant(456))
    .removeHeader("bar")
    .to("mock:b")
    // only merge in the message headers foo or bar
    .claimCheck(ClaimCheckOperation.Pop, null, "header:(foo|bar)")
    .to("mock:c");

10.4.4. XML 예

다음 예제에서는 푸시팝업 작업을 보여줍니다.

<route>
  <from uri="direct:start"/>
  <to uri="mock:a"/>
  <claimCheck operation="Push"/>
  <transform>
    <constant>Bye World</constant>
  </transform>
  <to uri="mock:b"/>
  <claimCheck operation="Pop"/>
  <to uri="mock:c"/>
</route>

다음은 GetSet 작업을 사용하는 예입니다. 예에서는 foo 키를 사용합니다.

<route>
  <from uri="direct:start"/>
  <to uri="mock:a"/>
  <claimCheck operation="Set" key="foo"/>
  <transform>
    <constant>Bye World</constant>
  </transform>
  <to uri="mock:b"/>
  <claimCheck operation="Get" key="foo"/>
  <to uri="mock:c"/>
  <transform>
    <constant>Hi World</constant>
  </transform>
  <to uri="mock:d"/>
  <claimCheck operation="Get" key="foo"/>
  <to uri="mock:e"/>
</route>
참고

데이터를 제거하지 않기 때문에 Get 작업을 사용하여 동일한 데이터를 두 번 가져올 수 있습니다. 그러나 데이터를 한 번 가져오려면 GetAndRemove 작업을 사용할 수 있습니다.

다음 예제에서는 filter 옵션을 사용하여 헤더를 foo 또는 bar 로 가져오는 방법을 보여줍니다.

<route>
  <from uri="direct:start"/>
  <to uri="mock:a"/>
  <claimCheck operation="Push"/>
  <transform>
    <constant>Bye World</constant>
  </transform>
  <setHeader headerName="foo">
    <constant>456</constant>
  </setHeader>
  <removeHeader headerName="bar"/>
  <to uri="mock:b"/>
  <!-- only merge in the message headers foo or bar -->
  <claimCheck operation="Pop" filter="header:(foo|bar)"/>
  <to uri="mock:c"/>
</route>

10.5. 정렬

10.5.1. 정렬

정렬 패턴은 메시지 본문에 정렬할 수 있는 항목 목록이 포함되어 있다고 가정하여 메시지 본문의 내용을 정렬하는 데 사용됩니다.

기본적으로 메시지의 내용은 숫자 값 또는 문자열을 처리하는 기본 비교기를 사용하여 정렬됩니다. 고유한 비교기를 제공할 수 있으며 정렬할 목록을 반환하는 식을 지정할 수 있습니다(표현식은 java.util.List로 변환할 수 있어야 함).

10.5.2. Java DSL 예

다음 예제에서는 줄 바꿈 문자에서 토큰을 사용하여 정렬할 항목 목록을 생성합니다.

from("file://inbox").sort(body().tokenize("\n")).to("bean:MyServiceBean.processLine");

고유한 비교기를 sort() 의 두 번째 인수로 전달할 수 있습니다.

from("file://inbox").sort(body().tokenize("\n"), new MyReverseComparator()).to("bean:MyServiceBean.processLine");

10.5.3. XML 구성 예

Spring XML에서 동일한 경로를 구성할 수 있습니다.

다음 예제에서는 줄 바꿈 문자에서 토큰을 사용하여 정렬할 항목 목록을 생성합니다.

<route>
  <from uri="file://inbox"/>
  <sort>
    <simple>body</simple>
  </sort>
  <beanRef ref="myServiceBean" method="processLine"/>
</route>

사용자 지정 비교기를 사용하려면 이를 Spring 8080으로 참조할 수 있습니다.

<route>
  <from uri="file://inbox"/>
  <sort comparatorRef="myReverseComparator">
    <simple>body</simple>
  </sort>
  <beanRef ref="MyServiceBean" method="processLine"/>
</route>

<bean id="myReverseComparator" class="com.mycompany.MyReverseComparator"/>

& lt;simple > 외에도 목록을 반환하는 동안 원하는 언어를 사용하여 표현식을 제공할 수 있습니다.

10.5.4. 옵션

sort DSL 명령은 다음 옵션을 지원합니다.

이름

기본값

설명

comparatorRef

 

메시지 본문을 정렬하는 데 사용할 사용자 지정 java.util.Comparator 를 나타냅니다. Camel은 기본적으로 A.Z 정렬을 수행하는 비교기를 사용합니다.

10.6. Transformer

Transformer는 경로 정의에서 선언된 Input Type 및/또는 Output Type 에 따라 메시지의 선언적 변환을 수행합니다. 기본 camel 메시지는 DataType 으로 표시되는 메시지 유형을 보유하는 DataTypeAware 를 구현합니다.

10.6.1. 변환기는 어떻게 작동합니까?

경로 정의는 입력 유형 및/또는 출력 유형을 선언합니다. 입력 유형 및/또는 출력 유형이 런타임 시 메시지 유형 과 다른 경우 camel 내부 프로세서는 Transformer를 찾습니다. Transformer는 현재 메시지 유형을 예상 메시지 유형으로 변환합니다. 메시지가 성공적으로 변환되거나 메시지가 이미 예상된 유형인 경우 메시지 데이터 유형이 업데이트됩니다.

10.6.1.1. 데이터 유형 형식

데이터 유형의 형식은 scheme:name 입니다. 여기서 schemejava,xml 또는 json 과 같은 데이터 모델의 유형입니다. name 은 데이터 형식 이름입니다.

참고

scheme 만 지정하는 경우 해당 스키마와 모든 데이터 형식과 일치합니다.

10.6.1.2. 지원되는 변환

Transformer설명

데이터 형식 변환기

데이터 형식을 사용하여 변환

끝점 변환기

Endpoint를 사용하여 변환

사용자 정의 변환기

사용자 지정 transformer 클래스를 사용하여 변환합니다.

10.6.1.3. 공통 옵션

모든 변환기에는 다음과 같은 일반적인 옵션이 있어 변환자에 의해 지원되는 데이터 유형을 지정합니다.

중요

scheme 또는 fromTypetoType 둘 다 지정해야 합니다.

이름설명

스키마

xml 또는 json 과 같은 데이터 모델의 유형입니다. 예를 들어 xml 가 지정되면 변환기가 모든 java -> xml 및 xml -> java 변환에 적용됩니다.

fromType

변환하기 위한 데이터 유형입니다.

toType

변환할 데이터 유형입니다.

10.6.1.4. DataFormat Transformer 옵션

이름설명

type

데이터 형식 유형

ref

데이터 형식 ID 참조

bindy DataFormat 유형을 지정하는 예입니다.

Java DSL:

BindyDataFormat bindy = new BindyDataFormat();
bindy.setType(BindyType.Csv);
bindy.setClassType(com.example.Order.class);
transformer()
    .fromType(com.example.Order.class)
    .toType("csv:CSVOrder")
    .withDataFormat(bindy);

XML DSL:

<dataFormatTransformer fromType="java:com.example.Order" toType="csv:CSVOrder">
    <bindy id="csvdf" type="Csv" classType="com.example.Order"/>
</dataFormatTransformer>

10.6.2. 끝점 변환 옵션

이름설명

ref

끝점 ID 참조

URI

엔드포인트 URI

Java DSL에서 끝점 URI를 지정하는 예는 다음과 같습니다.

transformer()
    .fromType("xml")
    .toType("json")
    .withUri("dozer:myDozer?mappingFile=myMapping.xml...");

XML DSL에서 끝점 ref를 지정하는 예:

<transformers>
<endpointTransformer ref="myDozerEndpoint" fromType="xml" toType="json"/>
</transformers>

10.6.3. 사용자 정의 변환 옵션

참고

Transformer는 org.apache.camel.spi.Transformer의 하위 클래스여야 합니다.

이름설명

ref

사용자 정의 Transformer metrics ID 참조

className

사용자 정의 Transformer 클래스의 정규화된 클래스 이름입니다.

사용자 정의 Transformer 클래스를 지정하는 예입니다.

Java DSL:

transformer()
    .fromType("xml")
    .toType("json")
    .withJava(com.example.MyCustomTransformer.class);

XML DSL:

<transformers>
<customTransformer className="com.example.MyCustomTransformer" fromType="xml" toType="json"/>
</transformers>

10.6.4. Transformer 예

이 예제는 두 부분으로, 첫 번째 부분은 메시지를 변환하는 Endpoint Transformer를 선언합니다. 두 번째 부분은 변환기가 경로에 적용되는 방법을 보여줍니다.

10.6.4.1. 부분 I

xslt 구성 요소를 사용하여 xml:ABCOrder 에서 xml:XYZOrder 로 변환하는 Endpoint Transformer를 선언합니다.

Java DSL:

transformer()
    .fromType("xml:ABCOrder")
    .toType("xml:XYZOrder")
    .withUri("xslt:transform.xsl");

XML DSL:

<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
    <transformers>
        <endpointTransformer uri="xslt:transform.xsl" fromType="xml:ABCOrder" toType="xml:XYZOrder"/>
    </transformers>
    ....
</camelContext>

10.6.4.2. Part II

직접:abc 끝점이 직접: xyz 로 메시지를 보낼 때 위의 변환기가 다음 경로 정의에 적용됩니다.

Java DSL:

from("direct:abc")
    .inputType("xml:ABCOrder")
    .to("direct:xyz");
from("direct:xyz")
    .inputType("xml:XYZOrder")
    .to("somewhere:else");

XML DSL:

<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
    <route>
        <from uri="direct:abc"/>
        <inputType urn="xml:ABCOrder"/>
        <to uri="direct:xyz"/>
    </route>
    <route>
        <from uri="direct:xyz"/>
        <inputType urn="xml:XYZOrder"/>
        <to uri="somewhere:else"/>
    </route>
</camelContext>

10.7. 검증기

유효성 검사기에서는 예상되는 메시지 유형을 선언하는 경로 정의에서 선언된 Input Type 및/또는 출력 유형에 따라 메시지의 선언적 유효성 검사를 수행합니다.

참고

검증은 형식 선언의 validate 속성이 true인 경우에만 수행됩니다.

Input Type 및/또는 Output Type 선언에서 validate 속성이 true이면 내부 프로세서에서 해당 Validator를 찾습니다.

10.7.1. 데이터 유형 형식

데이터 유형의 형식은 scheme: name 입니다. 여기서 schemejava,xml 또는 json 과 같은 데이터 모델의 유형입니다.

10.7.2. 지원되는 유효성 검사기

검증기설명

서술자 유효성 검사기

Expression 또는 Predicate를 사용하여 검증

엔드포인트 유효성 검사기

유효성 검사 구성 요소 또는 Cryostat 유효성 검사 구성 요소와 같은 유효성 검사 구성 요소와 함께 사용할 끝점으로 전달하여 검증합니다.

사용자 정의 유효성 검사기

사용자 정의 검증기 클래스를 사용하여 검증합니다. 검증자는 org.apache.camel.spi.Validator의 하위 클래스여야 합니다.

10.7.3. 공통 옵션

모든 검증기에는 유효성을 검사할 Data 유형을 지정하는 type 옵션이 포함되어야 합니다.

10.7.4. 서술자 유효성 검사 옵션

이름설명

expression

유효성 검사에 사용할 표현식 또는 서술자입니다.

검증 서술자를 지정하는 예제:

Java DSL:

validator()
    .type("csv:CSVOrder")
    .withExpression(bodyAs(String.class).contains("{name:XOrder}"));

XML DSL:

<predicateValidator Type="csv:CSVOrder">
    <simple>${body} contains 'name:XOrder'</simple>
</predicateValidator>

10.7.5. 엔드포인트 유효성 검사 옵션

이름설명

ref

엔드 포인트 ID에 대한 참조입니다.

URI

엔드포인트 URI.

Java DSL에서 끝점 URI를 지정하는 예제:

validator()
    .type("xml")
    .withUri("validator:xsd/schema.xsd");

XML DSL에서 끝점 ref를 지정하는 예제:

<validators>
<endpointValidator uri="validator:xsd/schema.xsd" type="xml"/>
</validators>
참고

Endpoint Validator는 메시지를 지정된 엔드포인트로 전달합니다. 위의 예에서 camel은 유효성 검사 구성 요소인 끝점에 메시지를 전달합니다. Cryostat 유효성 검사 구성 요소와 같은 다른 검증 구성 요소를 사용할 수도 있습니다.

10.7.6. 사용자 정의 검증 옵션

참고

검증자는 org.apache.camel.spi.Validator의 하위 클래스여야 합니다.

이름설명

ref

사용자 정의 Validator pin ID에 대한 참조입니다.

className

사용자 정의 Validator 클래스의 정규화된 클래스 이름입니다.

사용자 정의 Validator 클래스를 지정하는 예입니다.

Java DSL:

validator()
    .type("json")
    .withJava(com.example.MyCustomValidator.class);

XML DSL:

<validators>
<customValidator className="com.example.MyCustomValidator" type="json"/>
</validators>

10.7.7. 검증기 예

이 예제는 두 부분으로, 첫 번째 부분은 메시지의 유효성을 검사하는 Endpoint Validator를 선언합니다. 두 번째 부분은 검증기가 경로에 적용되는 방법을 보여줍니다.

10.7.7.1. 부분 I

유효성 검사기 구성 요소를 사용하여 xml:ABCOrder 에서 유효성을 검사하는 Endpoint Validator를 선언합니다.

Java DSL:

validator()
    .type("xml:ABCOrder")
    .withUri("validator:xsd/schema.xsd");

XML DSL:

<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
    <validators>
        <endpointValidator uri="validator:xsd/schema.xsd" type="xml:ABCOrder"/>
    </validators>
</camelContext>

10.7.7.2. Part II

위의 검증자는 direct:abc 엔드포인트가 메시지를 수신할 때 다음 경로 정의에 적용됩니다.

참고

inputTypeWithValidate 는 Java DSL에서 inputType 대신 사용되며 inputType 선언의 validate 속성은 XML DSL에서 true 로 설정됩니다.

Java DSL:

from("direct:abc")
    .inputTypeWithValidate("xml:ABCOrder")
    .log("${body}");

XML DSL:

<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
    <route>
        <from uri="direct:abc"/>
        <inputType urn="xml:ABCOrder" validate="true"/>
        <log message="${body}"/>
    </route>
</camelContext>

10.8. 검증

10.8.1. 개요

validate 패턴은 메시지의 콘텐츠가 유효한지 여부를 확인하는 편리한 구문을 제공합니다. validate DSL 명령은 서술자 표현식을 유일한 인수로 사용합니다. 서술자가 true 로 평가되면 경로가 정상적으로 처리됩니다. 서술자가 false 로 평가되면 PredicateValidationException 이 발생합니다.

10.8.2. Java DSL 예

다음 경로는 정규식을 사용하여 현재 메시지의 본문을 검증합니다.

from("jms:queue:incoming")
  .validate(body(String.class).regex("^\\w{10}\\,\\d{2}\\,\\w{24}$"))
  .to("bean:MyServiceBean.processLine");

다음과 같이 메시지 header Cryostat- Cryostat의 유효성을 검증할 수도 있습니다.

from("jms:queue:incoming")
  .validate(header("bar").isGreaterThan(100))
  .to("bean:MyServiceBean.processLine");

간단한 표현식 언어로 validate를 사용할 수 있습니다.

from("jms:queue:incoming")
  .validate(simple("${in.header.bar} == 100"))
  .to("bean:MyServiceBean.processLine");

10.8.3. XML DSL 예

XML DSL에서 유효성을 검사하기 위해 권장되는 접근 방식은 간단한 표현식 언어를 사용하는 것입니다.

<route>
  <from uri="jms:queue:incoming"/>
  <validate>
    <simple>${body} regex ^\\w{10}\\,\\d{2}\\,\\w{24}$</simple>
  </validate>
  <beanRef ref="myServiceBean" method="processLine"/>
</route>

<bean id="myServiceBean" class="com.mycompany.MyServiceBean"/>

다음과 같이 메시지 header Cryostat- Cryostat의 유효성을 검증할 수도 있습니다.

<route>
  <from uri="jms:queue:incoming"/>
  <validate>
    <simple>${in.header.bar} == 100</simple>
  </validate>
  <beanRef ref="myServiceBean" method="processLine"/>
</route>

<bean id="myServiceBean" class="com.mycompany.MyServiceBean"/>

11장. 메시징 끝점

초록

메시징 끝점 패턴은 끝점에서 구성할 수 있는 다양한 기능 및 서비스 특성을 설명합니다.

11.1. 메시징 매퍼

11.1.1. 개요

메시징 매퍼 패턴은 도메인 개체를 정식 메시지 형식으로 매핑하는 방법을 설명합니다. 여기서 메시지 형식이 가능한 플랫폼 중립으로 선택됩니다. 선택한 메시지 형식은 6.5절. “메시지 버스” 를 통한 전송에 적합해야 합니다. 여기서 메시지 버스는 다양한 다른 시스템을 통합하기 위한 백본이며, 그 중 일부는 개체 지향적이지 않을 수 있습니다.

다양한 접근 방식을 사용할 수 있지만 모두 메시징 매퍼의 요구 사항을 충족하는 것은 아닙니다. 예를 들어 오브젝트를 전송하는 명확한 방법은 모호하지 않은 인코딩(Java에서 기본적으로 지원)을 사용하여 데이터 스트림에 오브젝트를 작성할 수 있는 개체 직렬화 를 사용하는 것입니다. 그러나 직렬화 형식은 Java 애플리케이션에서만 이해되므로 메시징 매퍼 패턴에 사용하기에 적합한 방법은 아닙니다. Java 개체 직렬화는 원래 애플리케이션과 메시징 시스템의 다른 애플리케이션 간에 임피던스 불일치를 생성합니다.

메시징 매퍼의 요구 사항은 다음과 같이 요약할 수 있습니다.

  • 도메인 개체를 전송하는 데 사용되는 표준 메시지 형식은 개체 지향이 아닌 애플리케이션에서 사용하는 데 적합해야 합니다.
  • 매퍼 코드는 도메인 개체 코드와 메시징 인프라 모두에서 별도로 구현해야 합니다. Apache Camel은 경로에 매퍼 코드를 삽입하는 데 사용할 수 있는 후크를 제공하여 이러한 요구 사항을 충족할 수 있도록 지원합니다.
  • 매퍼는 상속, 개체 참조 및 개체 트리와 같은 특정 개체 지향 개념을 처리하는 효과적인 방법을 찾아야 할 수 있습니다. 이러한 문제의 복잡성은 애플리케이션마다 다르지만 매퍼 구현의 목적은 개체 지향이 아닌 애플리케이션에서 효과적으로 처리할 수 있는 메시지를 생성하는 것입니다.

11.1.2. 매핑할 오브젝트 찾기

다음 메커니즘 중 하나를 사용하여 매핑할 오브젝트를 찾을 수 있습니다.

  • 등록된 8080을 찾습니다. 싱글톤 오브젝트 및 적은 수의 오브젝트의 경우 CamelContext 레지스트리를 사용하여 빈에 대한 참조를 저장할 수 있습니다. 예를 들어, 빈 인스턴스가 Spring XML을 사용하여 인스턴스화되면 레지스트리에 자동으로 입력되며, 이 레지스트리의 id 속성 값으로 빈이 식별됩니다.
  • JoSQL 언어를 사용하여 오브젝트를 선택합니다. 액세스하려는 모든 오브젝트가 런타임에 이미 인스턴스화되어 있는 경우, JoSQL 언어를 사용하여 특정 오브젝트(또는 오브젝트)를 찾을 수 있습니다. 예를 들어 이름 VLAN 속성이 있고 들어오는 메시지에 UserName 헤더가 있는 org.apache.camel.builder.Person 클래스가 있는 경우 다음 코드를 사용하여 UserName 헤더와 이름 속성이 있는 오브젝트를 선택할 수 있습니다.

    import static org.apache.camel.builder.sql.SqlBuilder.sql;
    import org.apache.camel.Expression;
    ...
    Expression expression = sql("SELECT * FROM org.apache.camel.builder.sql.Person where name = :UserName");
    Object value = expression.evaluate(exchange);

    여기서 :HeaderName 라는 구문은 JoSQL 표현식의 헤더 값을 대체하는 데 사용됩니다.

  • 보다 확장 가능한 솔루션의 경우 데이터베이스에서 개체 데이터를 읽을 필요가 있을 수 있습니다.For a more scalable solution, it might be necessary to read object data from a database. 경우에 따라 기존 개체 지향 애플리케이션에서 이미 데이터베이스에서 개체를 로드할 수 있는 finder 개체를 제공할 수 있습니다. 다른 경우에는 데이터베이스에서 오브젝트를 추출하기 위해 일부 사용자 지정 코드를 작성해야 할 수 있으며, 이러한 경우 JDBC 구성 요소와 SQL 구성 요소가 유용할 수 있습니다.

11.2. 이벤트 기반 소비자

11.2.1. 개요

그림 11.1. “이벤트 기반 소비자 패턴” 에 표시된 이벤트 중심 소비자 패턴은 Apache Camel 구성 요소에서 소비자 끝점을 구현하는 패턴이며 Apache Camel에서 사용자 지정 구성 요소를 개발해야 하는 개발자와만 관련이 있습니다. 기존 구성 요소에는 이미 소비자 구현 패턴이 하드 연결되어 있습니다.

그림 11.1. 이벤트 기반 소비자 패턴

이벤트 기반 소비자 패턴

이 패턴을 따르는 소비자는 들어오는 메시지가 수신될 때마다 메시징 채널 또는 전송 계층에서 자동으로 호출하는 이벤트 메서드를 제공합니다. 이벤트 중심 소비자 패턴의 특성 중 하나는 소비자 끝점 자체가 들어오는 메시지를 처리하는 스레드를 제공하지 않는다는 것입니다. 대신 기본 전송 또는 메시징 채널은 노출된 이벤트 메서드(메시지 처리 기간 동안 차단)를 호출할 때 프로세서 스레드를 암시적으로 제공합니다.

이 구현 패턴에 대한 자세한 내용은 38.1.3절. “소비자 패턴 및 스레드”41장. 소비자 인터페이스 을 참조하십시오.

11.3. 폴링 소비자

11.3.1. 개요

그림 11.2. “폴링 소비자 패턴” 에 표시된 폴링 소비자 패턴은 Apache Camel 구성 요소에서 소비자 끝점을 구현하기 위한 패턴이므로 Apache Camel에서 사용자 지정 구성 요소를 개발해야 하는 프로그래머와만 관련이 있습니다. 기존 구성 요소에는 이미 소비자 구현 패턴이 하드 연결되어 있습니다.

이 패턴을 따르는 소비자는 폴링 방법, receive(), receive(long timeout)수신하며, 모니터링된 리소스에서 사용할 수 있는 경우 새 교환 오브젝트를 반환하는NoWait() 를 수신합니다. 폴링 소비자 구현에서는 폴링을 수행하려면 자체 스레드 풀을 제공해야 합니다.

이 구현 패턴에 대한 자세한 내용은 38.1.3절. “소비자 패턴 및 스레드”, 41장. 소비자 인터페이스, 37.3절. “소비자 템플릿 사용” 를 참조하십시오.

그림 11.2. 폴링 소비자 패턴

소비자 패턴 폴링

11.3.2. 예약된 폴링 소비자

Apache Camel 소비자 끝점의 대부분은 경로 시작 시 메시지를 수신하기 위해 예약된 폴링 패턴을 사용합니다. 즉, 엔드포인트가 이벤트 중심 소비자 인터페이스를 구현하는 것으로 표시되지만, 내부적으로 예약된 폴링은 엔드포인트에 들어오는 메시지를 제공하는 리소스를 모니터링하는 데 사용됩니다.

이 패턴을 구현하는 방법에 대한 자세한 내용은 41.2절. “소비자 인터페이스 구현” 을 참조하십시오.

11.3.3. Quartz 구성 요소

quartz 구성 요소를 사용하여 Quartz 엔터프라이즈 스케줄러를 사용하여 예약된 메시지를 전달할 수 있습니다. 자세한 내용은 Apache Camel 구성 요소 참조 가이드 Quartz 구성 요소의 Quartz 를 참조하십시오.

11.4. 경쟁 소비자

11.4.1. 개요

그림 11.3. “경쟁 소비자 패턴” 에 표시된 경쟁 소비자 패턴을 사용하면 여러 소비자가 동일한 대기열에서 메시지를 가져올 수 있으며 각 메시지가 한 번만 사용됩니다. 이 패턴은 직렬 메시지 처리를 동시 메시지 처리(응답 대기 시간 감소)로 교체하는 데 사용할 수 있습니다.

그림 11.3. 경쟁 소비자 패턴

소비자 패턴 경쟁

다음 구성 요소는 경쟁하는 소비자 패턴을 보여줍니다.

11.4.2. JMS 기반 경쟁 소비자

일반 JMS 대기열은 암시적으로 각 메시지를 한 번에만 사용할 수 있도록 보장합니다. 따라서 JMS 대기열은 경쟁하는 소비자 패턴을 자동으로 지원합니다. 예를 들어 다음과 같이 JMS 대기열인 HighVolumeQ 에서 메시지를 가져오는 경쟁적인 세 소비자를 정의할 수 있습니다.

from("jms:HighVolumeQ").to("cxf:bean:replica01");
from("jms:HighVolumeQ").to("cxf:bean:replica02");
from("jms:HighVolumeQ").to("cxf:bean:replica03");

CXF(Web services) 끝점, replica01,replica02, replica03 인 경우 HighVolumeQ 큐의 메시지를 병렬로 처리합니다.

또는 경쟁하는 소비자의 스레드 풀을 생성하기 위해 JMS 쿼리 옵션인 concurrentConsumers 를 설정할 수 있습니다. 예를 들어 다음 경로는 지정된 대기열에서 메시지를 선택하는 세 가지 경쟁적인 스레드 풀을 생성합니다.

from("jms:HighVolumeQ?concurrentConsumers=3").to("cxf:bean:replica01");

그리고 concurrentConsumers 옵션은 다음과 같이 XML DSL에도 지정할 수 있습니다.

 <route>
   <from uri="jms:HighVolumeQ?concurrentConsumers=3"/>
   <to uri="cxf:bean:replica01"/>
 </route>
참고

JMS 주제는 경쟁하는 소비자 패턴을 지원할 수 없습니다. 정의에 따라 JMS 주제는 동일한 메시지의 여러 복사본을 다른 소비자에 전송하기 위한 것입니다. 따라서 경쟁하는 소비자 패턴과 호환되지 않습니다.

11.4.3. SEDA 기반 경쟁 소비자

SEDA 구성 요소의 목적은 계산을 단계로 분할하여 동시 처리를 단순화하는 것입니다. SEDA 엔드포인트는 기본적으로 메모리 내 차단 대기열을 캡슐화합니다( java.util.concurrent.BlockingQueue). 따라서 SEDA 엔드포인트를 사용하여 각 스테이지에서 여러 스레드를 사용할 수 있는 단계로 경로를 분할할 수 있습니다. 예를 들어 다음과 같이 두 단계로 구성된 SEDA 경로를 정의할 수 있습니다.

// Stage 1: Read messages from file system.
from("file://var/messages").to("seda:fanout");

// Stage 2: Perform concurrent processing (3 threads).
from("seda:fanout").to("cxf:bean:replica01");
from("seda:fanout").to("cxf:bean:replica02");
from("seda:fanout").to("cxf:bean:replica03");

첫 번째 단계에는 파일 끝점, file://var/messages 의 메시지를 사용하고 SEDA 끝점인 seda:fanout 로 라우팅하는 단일 스레드가 포함되어 있습니다. 두 번째 단계에는 cxf:bean:replica01 로 교환을 라우팅하는 스레드, cxf:bean:replica02.로 교환되는 스레드 및 cxf:bean:replica03 으로의 교환을 라우팅하는 스레드의 세 가지 스레드가 포함되어 있습니다. 이 세 개의 스레드는 차단 큐를 사용하여 구현되는 SEDA 엔드포인트에서 교환 인스턴스를 가져오기 위해 경쟁합니다. 차단 대기열은 잠금을 사용하여 두 개 이상의 스레드가 한 번에 큐에 액세스하지 못하도록 하기 때문에 각 교환 인스턴스마다 한 번만 사용할 수 있습니다.

SEDA 엔드포인트와 thread() 에서 생성한 스레드 풀의 차이점에 대한 자세한 내용은 Apache Camel 구성 요소 참조 가이드의 SEDA 구성 요소를 참조하십시오.

11.5. 메시지 Dispatcher

11.5.1. 개요

그림 11.4. “메시지 Dispatcher 패턴” 에 표시된 메시지 디스패처 패턴은 채널에서 메시지를 소비한 다음 로컬로 메시지를 처리하는 작업자에 로컬로 배포하는 데 사용됩니다. Apache Camel 애플리케이션에서 수행자는 일반적으로 경로의 다른 섹션으로 메시지를 전송하는 데 사용되는 프로세스 내 엔드포인트로 표시됩니다.

그림 11.4. 메시지 Dispatcher 패턴

메시지 디스패처 패턴

다음 방법 중 하나를 사용하여 Apache Camel에서 메시지 디스패치 패턴을 구현할 수 있습니다.

11.5.2. JMS 선택기

애플리케이션이 JMS 대기열의 메시지를 사용하는 경우 JMS 선택기 를 사용하여 메시지 디스패처 패턴을 구현할 수 있습니다. JMS 선택기는 JMS 헤더 및 JMS 속성을 포함하는 서술자 표현식입니다. 선택기가 true 로 평가되면 JMS 메시지가 소비자에 도달할 수 있으며 선택기가 false 로 평가되면 JMS 메시지가 차단됩니다. 많은 측면에서 JMS 선택기는 8.2절. “메시지 필터” 와 유사하지만 JMS 공급자 내에서 필터링이 구현되는 추가 이점이 있습니다. 즉, JMS 선택기는 Apache Camel 애플리케이션으로 전송되기 전에 메시지를 차단할 수 있습니다. 이는 상당한 효율성 이점을 제공합니다.

Apache Camel에서는 JMS 엔드포인트 URI에 선택기 쿼리 옵션을 설정하여 소비자 끝점에 JMS 선택기 를 정의할 수 있습니다. 예를 들면 다음과 같습니다.

from("jms:dispatcher?selector=CountryCode='US'").to("cxf:bean:replica01");
from("jms:dispatcher?selector=CountryCode='IE'").to("cxf:bean:replica02");
from("jms:dispatcher?selector=CountryCode='DE'").to("cxf:bean:replica03");

선택기 문자열에 표시되는 서술자는 SQL92 조건부 표현식 구문의 하위 집합을 기반으로 합니다(전체 세부 사항은 JMS 사양참조). 선택기 문자열에 나타나는 식별자는 JMS 헤더 또는 JMS 속성을 참조할 수 있습니다. 예를 들어 이전 경로에서 발신자는 Cryostat Code 라는 JMS 속성을 설정합니다.

Apache Camel 애플리케이션 내에서 메시지에 JMS 속성을 추가하려면 메시지 헤더(메시지 내 또는 외부 메시지)를 설정하여 이를 수행할 수 있습니다. JMS 엔드포인트를 읽거나 쓸 때 Apache Camel은 JMS 헤더 및 JMS 속성을 기본 메시지 헤더에 매핑합니다.

기술적으로 선택기 문자열은 application/x-www-form-urlencoded MIME 형식에 따라 인코딩된 URL이어야 합니다(html 사양참조). 실제로 &amp; (ampersand) 문자는 URI에서 각 쿼리 옵션을 구분하는 데 사용되므로 문제가 발생할 수 있습니다. & amp; 문자를 포함해야 하는 복잡한 선택기 문자열의 경우 java.net.URLEncoder 유틸리티 클래스를 사용하여 문자열을 인코딩할 수 있습니다. 예를 들면 다음과 같습니다.

from("jms:dispatcher?selector=" + java.net.URLEncoder.encode("CountryCode='US'","UTF-8")).
    to("cxf:bean:replica01");

UTF-8 인코딩을 사용해야 하는 위치.

11.5.3. ActiveMQ의 JMS 선택기

ActiveMQ 엔드포인트에 JMS 선택기를 정의할 수도 있습니다. 예를 들면 다음과 같습니다.

from("activemq:dispatcher?selector=CountryCode='US'").to("cxf:bean:replica01");
from("activemq:dispatcher?selector=CountryCode='IE'").to("cxf:bean:replica02");
from("activemq:dispatcher?selector=CountryCode='DE'").to("cxf:bean:replica03");

자세한 내용은 ActiveMQ: JMS SelectorsActiveMQ Message Properties 를 참조하십시오.

11.5.4. 콘텐츠 기반 라우터

콘텐츠 기반 라우터 패턴과 메시지 디스패처 패턴의 근본적인 차이점은 콘텐츠 기반 라우터가 물리적으로 분리된 대상(원격 끝점)에 메시지를 디스패치하고 메시지 디스패처가 동일한 프로세스 공간 내에서 로컬로 메시지를 디스패치한다는 것입니다. Apache Camel에서 이러한 두 패턴 간의 차이점은 대상 엔드포인트에 따라 결정됩니다. 동일한 라우터 논리는 콘텐츠 기반 라우터와 메시지 디스패처를 모두 구현하는 데 사용됩니다. 대상 끝점이 원격인 경우 경로는 콘텐츠 기반 라우터를 정의합니다. 대상 끝점이 프로세스 중이면 경로는 메시지 디스패처를 정의합니다.

콘텐츠 기반 라우터 패턴을 사용하는 방법에 대한 자세한 내용 및 예제는 8.1절. “콘텐츠 기반 라우터” 에서 참조하십시오.

11.6. 선택적 소비자

11.6.1. 개요

그림 11.5. “선택적 소비자 패턴” 에 표시된 선택적 소비자 패턴은 수신 메시지에 필터를 적용하여 특정 선택 기준을 충족하는 메시지만 처리하는 소비자를 설명합니다.

그림 11.5. 선택적 소비자 패턴

선택적 소비자 패턴

다음 방법 중 하나를 사용하여 Apache Camel에서 선택적 소비자 패턴을 구현할 수 있습니다.

11.6.2. JMS 선택기

JMS 선택기는 JMS 헤더 및 JMS 속성을 포함하는 서술자 표현식입니다. 선택기가 true 로 평가되면 JMS 메시지가 소비자에 도달할 수 있으며 선택기가 false 로 평가되면 JMS 메시지가 차단됩니다. 예를 들어 큐의 메시지를 사용하고 국가 코드 속성이 US 인 메시지만 선택하려면 다음 Java DSL 경로를 사용할 수 있습니다.

from("jms:selective?selector=" + java.net.URLEncoder.encode("CountryCode='US'","UTF-8")).
    to("cxf:bean:replica01");

쿼리 옵션 구문 분석 문제를 방지하려면 선택기 문자열인 selector 문자열( Code='US' )이 URL로 인코딩되어야 합니다( UTF-8 문자 사용). 이 예에서는 JMS 속성인 Code 가 보낸 사람에 의해 설정되었다고 가정합니다. JMS 선택기에 대한 자세한 내용은 “JMS 선택기” 을 참조하십시오.

참고

선택기가 JMS 큐에 적용되는 경우 선택되지 않은 메시지는 큐에서 남아 있으며 동일한 큐에 연결된 다른 소비자가 사용할 수 있습니다.

11.6.3. ActiveMQ의 JMS 선택기

ActiveMQ 엔드포인트에 JMS 선택기를 정의할 수도 있습니다. 예를 들면 다음과 같습니다.

from("acivemq:selective?selector=" + java.net.URLEncoder.encode("CountryCode='US'","UTF-8")).
    to("cxf:bean:replica01");

자세한 내용은 ActiveMQ: JMS SelectorsActiveMQ Message Properties 를 참조하십시오.

11.6.4. 메시지 필터

소비자 끝점에서 선택기를 설정할 수 없는 경우 대신 필터 프로세서를 경로에 삽입할 수 있습니다. 예를 들어 다음과 같이 Java DSL을 사용하여 미국 국가 코드가 있는 메시지만 처리하는 선택적 소비자를 정의할 수 있습니다.

from("seda:a").filter(header("CountryCode").isEqualTo("US")).process(myProcessor);

다음과 같이 XML 구성을 사용하여 동일한 경로를 정의할 수 있습니다.

<camelContext id="buildCustomProcessorWithFilter" xmlns="http://camel.apache.org/schema/spring">
  <route>
    <from uri="seda:a"/>
    <filter>
      <xpath>$CountryCode = 'US'</xpath>
      <process ref="#myProcessor"/>
    </filter>
  </route>
</camelContext>

Apache Camel 필터 프로세서에 대한 자세한 내용은 8.2절. “메시지 필터” 을 참조하십시오.

주의

메시지 필터를 사용하여 JMS 대기열에서 메시지를 선택합니다. 필터 프로세서를 사용하는 경우 차단된 메시지는 간단히 삭제됩니다. 따라서 대기열에서 메시지가 사용되는 경우(각 메시지를 한 번만 사용할 수 있습니다. 11.4절. “경쟁 소비자”참조) 차단된 메시지는 전혀 처리되지 않습니다. 이는 원하는 동작이 아닐 수 있습니다.

11.7. Cryostat 구독자

11.7.1. 개요

그림 11.6. “Cryostat 구독자 패턴” 에 표시된 대로 지속성 구독자 는 소비자가 메시징 시스템에서 연결이 끊긴 동안 전송된 메시지를 포함하여 특정 6.2절. “게시-서브스크립션 채널” 채널을 통해 전송되는 모든 메시지를 수신하려는 소비자입니다. 이를 위해서는 메시징 시스템이 연결이 끊긴 소비자로 나중에 재생하기 위한 메시지를 저장해야 합니다. 또한 소비자가 기존 서브스크립션을 구축하고자 한다는 것을 나타내는 메커니즘이 있어야 합니다. 일반적으로 게시-구독 채널(또는 topic)은 다음과 같이 작동합니다.

  • 비독일 수 있는 구독자 으며 연결연결이 끊어진 두 가지 상태가 있을 수 있습니다. 실행 불가능한 구독자는 주제에 연결되어 있지만 주제의 모든 메시지를 실시간으로 수신합니다. 그러나 실행 불가능한 구독자는 구독자의 연결이 끊어진 동안 해당 주제로 보낸 메시지를 받지 않습니다.
  • 강인 구독자 Cryo stat- Cryostat는 두 가지 상태, 즉 연결비활성 상태가 있을 수 있습니다. 비활성 상태는 지속성 구독자가 주제와의 연결이 끊어지지만 임시로 들어오는 메시지를 수신하려는 것을 의미합니다. ity 구독자가 항목에 다시 연결되면 비활성 상태인 동안 전송된 모든 메시지를 재생합니다.

그림 11.6. Cryostat 구독자 패턴

Cryostat 구독자 패턴

11.7.2. JMS Cryostat 구독자

JMS 구성 요소는 지속성 구독자 패턴을 구현합니다. JMS 끝점에서 Cryostat 서브스크립션을 설정하려면 이 특정 연결을 식별하는 클라이언트 ID 와 Cryo stat 서브스크립션 이름을 지정해야 합니다. 예를 들어 다음 경로는 클라이언트 ID가 conn01 인 JMS 주제, news 에 대한 Cryostat 서브스크립션을 설정하고, audit .Doe의 Cryostat 서브스크립션 이름을 설정합니다.

from("jms:topic:news?clientId=conn01&durableSubscriptionName=John.Doe").
    to("cxf:bean:newsprocessor");

ActiveMQ 끝점을 사용하여 Cryostat 서브스크립션을 설정할 수도 있습니다.

from("activemq:topic:news?clientId=conn01&durableSubscriptionName=John.Doe").
    to("cxf:bean:newsprocessor");

들어오는 메시지를 동시에 처리하려는 경우 SEDA 끝점을 사용하여 다음과 같이 여러 병렬 세그먼트로 경로를 배포할 수 있습니다.

from("jms:topic:news?clientId=conn01&durableSubscriptionName=John.Doe").
    to("seda:fanout");

from("seda:fanout").to("cxf:bean:newsproc01");
from("seda:fanout").to("cxf:bean:newsproc02");
from("seda:fanout").to("cxf:bean:newsproc03");

SEDA 구성 요소가 경쟁 소비자 패턴을 지원하므로 각 메시지가 한 번만 처리되는 경우입니다.

11.7.3. 대체 예

또 다른 대안은 사용할 수 없는 경우 SEDA 의 경우 11.5절. “메시지 Dispatcher” 또는 8.1절. “콘텐츠 기반 라우터”파일 또는 JPA 구성 요소와 결합한 것입니다.

다음은 JMS 주제의 구독자를 생성하는 간단한 예입니다.

Fluent Builders사용

 from("direct:start").to("activemq:topic:foo");

 from("activemq:topic:foo?clientId=1&durableSubscriptionName=bar1").to("mock:result1");

 from("activemq:topic:foo?clientId=2&durableSubscriptionName=bar2").to("mock:result2");

Spring XML Extensions사용

 <route>
     <from uri="direct:start"/>
     <to uri="activemq:topic:foo"/>
 </route>

 <route>
     <from uri="activemq:topic:foo?clientId=1&durableSubscriptionName=bar1"/>
     <to uri="mock:result1"/>
 </route>

 <route>
     <from uri="activemq:topic:foo?clientId=2&durableSubscriptionName=bar2"/>
     <to uri="mock:result2"/>
 </route>

다음은 JMS Cryostat 구독자의 또 다른 예이지만, 이번에는 가상 주제 를 사용합니다(레드 서브스크립션을 통해 AMQ에 의해 권장됨)

Fluent Builders 사용

 from("direct:start").to("activemq:topic:VirtualTopic.foo");

 from("activemq:queue:Consumer.1.VirtualTopic.foo").to("mock:result1");

 from("activemq:queue:Consumer.2.VirtualTopic.foo").to("mock:result2");

Spring XML Extensions사용

 <route>
     <from uri="direct:start"/>
     <to uri="activemq:topic:VirtualTopic.foo"/>
 </route>

 <route>
     <from uri="activemq:queue:Consumer.1.VirtualTopic.foo"/>
     <to uri="mock:result1"/>
 </route>

 <route>
     <from uri="activemq:queue:Consumer.2.VirtualTopic.foo"/>
     <to uri="mock:result2"/>
 </route>

11.8. idempotent 소비자

11.8.1. 개요

idempotent 소비자 패턴은 중복 메시지를 필터링하는 데 사용됩니다. 예를 들어 메시징 시스템과 소비자 끝점 간의 연결이 시스템의 일부 오류로 인해 갑자기 손실되는 시나리오를 고려해 보십시오. 메시지 전송 중 메시징 시스템이 메시지 전송 중이면 소비자가 마지막 메시지를 수신했는지의 여부를 명확하지 않을 수 있습니다. 전송 안정성을 개선하기 위해 메시징 시스템은 연결이 다시 설정되는 즉시 이러한 메시지를 다시 전송하도록 결정할 수 있습니다. 안타깝게도, 이는 소비자가 중복 메시지를 수신할 수 있는 위험을 수반하며, 경우에 따라 메시지를 복제하는 영향은 바람직하지 않은 결과를 초래할 수 있습니다(예: 계정의 합계를 초월하는 등). 이 시나리오에서 idempotent 소비자는 메시지 스트림에서 원하지 않는 중복을 제거하는 데 사용할 수 있습니다.

Camel은 다음과 같은 Idempotent Consumer 구현을 제공합니다.

11.8.2. 메모리 내 캐시를 사용하는 idempotent 소비자

Apache Camel에서 idempotent 소비자 패턴은 두 개의 인수를 사용하는 idempotentConsumer() 프로세서에 의해 구현됩니다.

  • 현재 메시지에 대한 메시지 ID 문자열을 반환하는 식 입니다.An expression that returns a message ID string for the current message.
  • messageIdRepository Cryostat- Cryostat는 메시지 ID 리포지토리에 대한 참조로, 수신된 모든 메시지의 ID를 저장합니다.

각 메시지가 들어오는 대로 idempotent 소비자 프로세서는 리포지토리에서 현재 메시지 ID를 조회하여 이 메시지가 이전에 표시되는지 확인합니다. yes인 경우 메시지가 삭제됩니다. 메시지가 전달되지 않으면 메시지가 허용되고 해당 ID가 리포지토리에 추가됩니다.

예 11.1. “메모리 내 캐시를 사용하여 메시지 복제 필터링” 에 표시된 코드는 TransactionID 헤더를 사용하여 중복을 필터링합니다.

예 11.1. 메모리 내 캐시를 사용하여 메시지 복제 필터링

import static org.apache.camel.processor.idempotent.MemoryMessageIdRepository.memoryMessageIdRepository;
...
RouteBuilder builder = new RouteBuilder() {
    public void configure() {
        from("seda:a")
          .idempotentConsumer(
             header("TransactionID"),
             memoryMessageIdRepository(200)
          ).to("seda:b");
    }
};

memoryMessageIdRepository(200) 를 호출하면 최대 200개의 메시지 ID를 보유할 수 있는 메모리 내 캐시가 생성됩니다.

XML 구성을 사용하여 idempotent 소비자를 정의할 수도 있습니다. 예를 들어 다음과 같이 XML로 이전 경로를 정의할 수 있습니다.

<camelContext id="buildIdempotentConsumer" xmlns="http://camel.apache.org/schema/spring">
  <route>
    <from uri="seda:a"/>
    <idempotentConsumer messageIdRepositoryRef="MsgIDRepos">
      <simple>header.TransactionID</simple>
      <to uri="seda:b"/>
    </idempotentConsumer>
  </route>
</camelContext>

<bean id="MsgIDRepos" class="org.apache.camel.processor.idempotent.MemoryMessageIdRepository">
    <!-- Specify the in-memory cache size. -->
    <constructor-arg type="int" value="200"/>
</bean>
참고

Camel 2.17에서 Idempotent Repository는 선택적 직렬화된 헤더를 지원합니다.

11.8.3. JPA 리포지토리가 있는 idempotent 소비자

메모리 내 캐시는 메모리가 부족하여 클러스터형 환경에서 작동하지 않는 단점이 있습니다. 이러한 단점을 극복하기 위해 대신 Java Persistent API(JPA) 기반 리포지토리를 사용할 수 있습니다. JPA 메시지 ID 리포지토리는 오브젝트 지향 데이터베이스를 사용하여 메시지 ID를 저장합니다. 예를 들어 다음과 같이 멱등 소비자에 JPA 리포지토리를 사용하는 경로를 정의할 수 있습니다.

import org.springframework.orm.jpa.JpaTemplate;

import org.apache.camel.spring.SpringRouteBuilder;
import static org.apache.camel.processor.idempotent.jpa.JpaMessageIdRepository.jpaMessageIdRepository;
...
RouteBuilder builder = new SpringRouteBuilder() {
    public void configure() {
        from("seda:a").idempotentConsumer(
          header("TransactionID"),
          jpaMessageIdRepository(bean(JpaTemplate.class), "myProcessorName")
        ).to("seda:b");
    }
};

JPA 메시지 ID 리포지토리는 다음 두 개의 인수로 초기화됩니다.

  • jpaTemplate instance Cryostat- Cryostat - JPA 데이터베이스의 처리 기능을 제공합니다.
  • 현재 멱등 소비자 프로세서를 나타냅니다.Represents the current idempotent consumer processor.

SpringRouteBuilder.bean() 메서드는 Spring XML 파일에 정의된 8080을 참조하는 바로 가기입니다. JpaTemplate 8080은 기본 JPA 데이터베이스에 대한 처리를 제공합니다. 이 빈을 구성하는 방법에 대한 자세한 내용은 JPA 설명서를 참조하십시오.

JPA 리포지토리 설정에 대한 자세한 내용은 JPA 구성 요소 문서, Spring JPA 문서 및 Camel JPA 단위 테스트 의 샘플 코드를 참조하십시오.

11.8.4. Spring XML 예

다음 예제에서는 myMessageId 헤더를 사용하여 중복을 필터링합니다.

<!-- repository for the idempotent consumer -->
<bean id="myRepo" class="org.apache.camel.processor.idempotent.MemoryIdempotentRepository"/>

<camelContext xmlns="http://camel.apache.org/schema/spring">
    <route>
        <from uri="direct:start"/>
        <idempotentConsumer messageIdRepositoryRef="myRepo">
            <!-- use the messageId header as key for identifying duplicate messages -->
            <header>messageId</header>
            <!-- if not a duplicate send it to this mock endpoint -->
            <to uri="mock:result"/>
        </idempotentConsumer>
    </route>
</camelContext>

11.8.5. JDBC 리포지토리가 있는 idempotent 소비자

idempotent 소비자 패턴에 메시지 ID를 저장하는 데 JDBC 리포지토리도 지원됩니다. JDBC 리포지토리의 구현은 SQL 구성 요소에서 제공하므로 Maven 빌드 시스템을 사용하는 경우 camel-sql 아티팩트에 대한 종속성을 추가합니다.

SQL 데이터베이스에 대한 연결을 인스턴스화하기 위해 Spring persistence API에서 SingleConnectionDataSource JDBC 래퍼 클래스를 사용할 수 있습니다. 예를 들어 HyperSQL 데이터베이스 인스턴스에 대한 JDBC 연결을 인스턴스화하려면 다음 JDBC 데이터 소스를 정의할 수 있습니다.

<bean id="dataSource" class="org.springframework.jdbc.datasource.SingleConnectionDataSource">
    <property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
    <property name="url" value="jdbc:hsqldb:mem:camel_jdbc"/>
    <property name="username" value="sa"/>
    <property name="password" value=""/>
</bean>
참고

위의 JDBC 데이터 소스는 메모리 전용 데이터베이스 인스턴스를 생성하는 HyperSQL mem 프로토콜을 사용합니다. 이는 실제로 지속되지 않은 HyperSQL 데이터베이스의 강력한 구현입니다.

이전 데이터 소스를 사용하여 다음과 같이 JDBC 메시지 ID 리포지토리를 사용하는 idempotent 소비자 패턴을 정의할 수 있습니다.

<bean id="messageIdRepository" class="org.apache.camel.processor.idempotent.jdbc.JdbcMessageIdRepository">
	<constructor-arg ref="dataSource" />
	<constructor-arg value="myProcessorName" />
</bean>

<camel:camelContext>
	<camel:errorHandler id="deadLetterChannel" type="DeadLetterChannel" deadLetterUri="mock:error">
		<camel:redeliveryPolicy maximumRedeliveries="0" maximumRedeliveryDelay="0" logStackTrace="false" />
	</camel:errorHandler>

	<camel:route id="JdbcMessageIdRepositoryTest" errorHandlerRef="deadLetterChannel">
		<camel:from uri="direct:start" />
		<camel:idempotentConsumer messageIdRepositoryRef="messageIdRepository">
			<camel:header>messageId</camel:header>
			<camel:to uri="mock:result" />
		</camel:idempotentConsumer>
	</camel:route>
	</camel:camelContext>

11.8.6. 경로에서 중복 메시지를 처리하는 방법

Camel 2.8 사용 가능

이제 skipDuplicate 옵션을 false 로 설정하여 idempotent 소비자가 중복 메시지를 라우팅하도록 지시할 수 있습니다. 그러나 “교환” 의 속성을 true로 설정하여 중복 메시지가 중복으로 표시되었습니다. 8.1절. “콘텐츠 기반 라우터” 또는 8.2절. “메시지 필터” 를 사용하여 이를 감지하고 중복 메시지를 처리하여 이 사실을 활용할 수 있습니다.

예를 들어 다음 예에서 8.2절. “메시지 필터” 를 사용하여 메시지를 중복 끝점으로 보낸 다음 해당 메시지의 계속 라우팅을 중지합니다.

from("direct:start")
     // instruct idempotent consumer to not skip duplicates as we will filter then our self
     .idempotentConsumer(header("messageId")).messageIdRepository(repo).skipDuplicate(false)
     .filter(property(Exchange.DUPLICATE_MESSAGE).isEqualTo(true))
         // filter out duplicate messages by sending them to someplace else and then stop
         .to("mock:duplicate")
         .stop()
     .end()
     // and here we process only new messages (no duplicates)
     .to("mock:result");

XML DSL의 샘플 예제는 다음과 같습니다.

 <!-- idempotent repository, just use a memory based for testing -->
 <bean id="myRepo" class="org.apache.camel.processor.idempotent.MemoryIdempotentRepository"/>

 <camelContext xmlns="http://camel.apache.org/schema/spring">
     <route>
         <from uri="direct:start"/>
         <!-- we do not want to skip any duplicate messages -->
         <idempotentConsumer messageIdRepositoryRef="myRepo" skipDuplicate="false">
             <!-- use the messageId header as key for identifying duplicate messages -->
             <header>messageId</header>
             <!-- we will to handle duplicate messages using a filter -->
             <filter>
                 <!-- the filter will only react on duplicate messages, if this property is set on the Exchange -->
                 <property>CamelDuplicateMessage</property>
                 <!-- and send the message to this mock, due its part of an unit test -->
                 <!-- but you can of course do anything as its part of the route -->
                 <to uri="mock:duplicate"/>
                 <!-- and then stop -->
                 <stop/>
             </filter>
             <!-- here we route only new messages -->
             <to uri="mock:result"/>
         </idempotentConsumer>
     </route>
 </camelContext>

11.8.7. 데이터 그리드를 사용하여 클러스터형 환경에서 중복 메시지를 처리하는 방법

클러스터형 환경에서 Camel을 실행하는 경우 메모리의 멱등 리포지토리가 작동하지 않습니다(위 참조). 중앙 데이터베이스를 설정하거나 Hazelcast 데이터 그리드를 기반으로 멱등 소비자 구현을 사용할 수 있습니다. Hazelcast는 멀티 캐스트를 통해 노드를 찾습니다(기본값 - tcp-ip의 Hazelcast 구성)는 맵 기반 리포지토리를 자동으로 생성합니다.

HazelcastIdempotentRepository idempotentRepo = new HazelcastIdempotentRepository("myrepo");

from("direct:in").idempotentConsumer(header("messageId"), idempotentRepo).to("mock:out");

리포지토리가 각 메시지 ID를 유지해야 하는 기간을 정의해야 합니다(기본값은 절대 삭제하지 않음). 메모리 부족을 방지하려면 Hazelcast 구성 을 기반으로 제거 전략을 생성해야 합니다. 자세한 내용은 Hazelcast 를 참조하십시오.

이 링크 참조:http://camel.apache.org/hazelcast-idempotent-repository-tutorial.html[Idempotent 리포지토리

Apache Karaf를 사용하여 두 클러스터 노드에 멱등 리포지토리를 설정하는 방법에 대한 자세한 내용은 튜토리얼]을 참조하십시오.

11.8.8. 옵션

Idempotent Consumer에는 다음과 같은 옵션이 있습니다.

옵션

Default

설명

eager

true

Camel 2.0: Eager는 Camel이 교환이 처리되기 전이나 후에 메시지를 리포지토리에 추가하는지 여부를 제어합니다. 이전에 활성화된 경우 Camel은 현재 메시지가 진행 중인 경우에도 중복 메시지를 감지할 수 있습니다. Camel을 비활성화하면 메시지가 성공적으로 처리된 경우에만 중복을 감지합니다.

messageIdRepositoryRef

null

레지스트리에서 조회할 IdempotentRepository 에 대한 참조입니다. 이 옵션은 XML DSL을 사용할 때 필요합니다.

skipDuplicate

true

Camel 2.8: 중복 메시지를 건너뛸지 여부를 설정합니다. false 로 설정하면 메시지가 계속됩니다. 그러나 “교환”Exchange.DUPLICATE_MESSAG 교환 속성을 부울.TRUE 값으로 설정하여 중복으로 표시되었습니다.

completionEager

false

Camel 2.16: 교환이 완료되면 Idempotent consumer eager를 완료할지 여부를 설정합니다.

completeEager 옵션을 true로 설정하면 교환이 멱등 소비자 패턴 블록의 끝까지 도달할 때 Idempotent Consumer가 완료를 트리거합니다. 그러나 엔드 블록 후에도 교환이 계속 라우팅되는 경우 멱등 소비자의 상태에는 영향을 미치지 않습니다.

completeEager 옵션을 false로 설정하면 교환이 완료되면 Idempotent Consumer가 완료를 트리거하고 라우팅됩니다. 그러나 블록이 종료된 후에도 교환이 계속 라우팅되는 경우 멱등 소비자의 상태에도 영향을 미칩니다. 예를 들어 교환이 실패하는 경우 예외로 인해 idempotent 소비자의 상태는 롤백이 됩니다.

11.9. 트랜잭션 클라이언트

11.9.1. 개요

그림 11.7. “트랜잭션 클라이언트 패턴” 에 표시된 트랜잭션 클라이언트 패턴은 트랜잭션에 참여할 수 있는 메시징 끝점을 나타냅니다. Apache Camel은 Spring 트랜잭션 관리를 사용하는 트랜잭션 을 지원합니다.

그림 11.7. 트랜잭션 클라이언트 패턴

트랜잭션 클라이언트 패턴

11.9.2. 트랜잭션 지향 끝점

일부 Apache Camel 끝점이 트랜잭션을 지원하는 것은 아닙니다. 트랜잭션 지향 끝점 (또는 TOE)이라고 합니다. 예를 들어 JMS 구성 요소와 ActiveMQ 구성 요소는 모두 트랜잭션을 지원합니다.

구성 요소에서 트랜잭션을 활성화하려면 구성 요소를 CamelContext 에 추가하기 전에 적절한 초기화를 수행해야 합니다. 트랜잭션 구성 요소를 명시적으로 초기화하기 위한 코드 작성이 포함됩니다.

11.9.3. 참고 자료

Apache Camel에서 트랜잭션 구성에 대한 자세한 내용은 이 가이드의 범위를 벗어납니다. 트랜잭션 사용 방법에 대한 자세한 내용은 Apache Camel 트랜잭션 가이드를 참조하십시오.

11.10. 메시징 게이트웨이

11.10.1. 개요

그림 11.8. “메시징 게이트웨이 패턴” 에 표시된 메시징 게이트웨이 패턴은 메시징 시스템과의 통합 방법을 설명합니다. 여기서 메시징 시스템의 API는 애플리케이션 수준의 구현에서 숨겨집니다. 보다 일반적인 예 중 하나는 동기 메서드 호출을 요청/응답 메시지 교환으로 변환하려는 경우입니다.

그림 11.8. 메시징 게이트웨이 패턴

메시징 게이트웨이 패턴

다음 Apache Camel 구성 요소는 이러한 종류의 메시징 시스템과의 통합을 제공합니다.

  • CXF
  • Cryostat 구성 요소

11.11. 서비스 활성화기

11.11.1. 개요

그림 11.9. “서비스 활성화 패턴” 에 표시된 서비스 활성화 패턴은 들어오는 요청 메시지에 대한 응답으로 서비스의 작업을 호출하는 시나리오를 설명합니다. 서비스 활성화기는 작업 매개 변수로 사용할 데이터를 호출하고 추출할 작업을 식별합니다. 마지막으로 서비스 활성화기는 메시지에서 추출된 데이터를 사용하여 작업을 호출합니다. 작업 호출은 oneway(요청만 해당) 또는 양방향(요청/반복)일 수 있습니다.

그림 11.9. 서비스 활성화 패턴

서비스 활성화자 패턴

많은 측면에서 서비스 활성화기가 기존의 원격 프로시저 호출(RPC)과 유사합니다. 여기서 작업 호출은 메시지로 인코딩됩니다. 가장 큰 차이점은 서비스 활성화자가 보다 유연해야 한다는 것입니다. RPC 프레임워크는 요청 및 응답 메시지 인코딩을 표준화하는 반면(예: 웹 서비스 작업은 Loki 메시지로 인코딩되는 반면, 서비스 활성화기는 일반적으로 메시징 시스템과 서비스 작업 간의 매핑을 방해해야 합니다.

11.11.2. Cryostat 통합

Apache Camel이 서비스 활성화 패턴을 지원하기 위해 제공하는 주요 메커니즘은 8080 통합 입니다. Cryostat 통합 은 들어오는 메시지를 Java 객체의 메서드 호출에 매핑하는 일반적인 프레임워크를 제공합니다. 예를 들어 Java fluent DSL은 등록된 Java Ignition에서 메서드를 호출하기 위해 경로에 삽입할 수 있는 utility () 및 8080Ref() 프로세서를 제공합니다. 메시지 데이터의 Java 메서드 매개 변수에 대한 자세한 매핑은 8080 바인딩에 따라 결정되며, 이 바인딩은 8080 클래스에 주석을 추가하여 구현할 수 있습니다.

예를 들어 Java 메서드 bankBean.getUserAccBalance() 를 호출하는 다음 경로를 사용하여 JMS/ActiveMQ 큐에서 들어오는 서비스 요청을 고려하십시오.

from("activemq:BalanceQueries")
  .setProperty("userid", xpath("/Account/BalanceQuery/UserID").stringResult())
  .beanRef("bankBean", "getUserAccBalance")
  .to("velocity:file:src/scripts/acc_balance.vm")
  .to("activemq:BalanceResults");

ActiveMQ 엔드포인트 activemq:BalanceQueries 에서 가져온 메시지에는 은행 계정의 사용자 ID를 제공하는 간단한 XML 형식이 있습니다. 예를 들면 다음과 같습니다.

<?xml version='1.0' encoding='UTF-8'?>
<Account>
  <BalanceQuery>
    <UserID>James.Strachan</UserID>
  </BalanceQuery>
</Account>

경로의 첫 번째 프로세서인 setProperty()In 메시지에서 사용자 ID를 추출하여 userid exchange 속성에 저장합니다. 8080을 호출한 후에는 In 헤더를 사용할 수 없으므로 헤더에 저장하는 것이 좋습니다.

서비스 활성화 단계는 ingress Ref() 프로세서에서 수행합니다. 이 프로세서는 들어오는 메시지를 bankBean VLAN ID로 식별되는 Java 개체의 getUserAccBalance() 메서드에 바인딩합니다. 다음 코드에서는 bankBean 클래스의 샘플 구현을 보여줍니다.

package tutorial;

import org.apache.camel.language.XPath;

public class BankBean {
    public int getUserAccBalance(@XPath("/Account/BalanceQuery/UserID") String user) {
        if (user.equals("James.Strachan")) {
            return 1200;
        }
        else {
            return 0;
        }
      }
}

메시지 데이터의 바인딩이 메서드 매개 변수에 의해 활성화되는 경우 @XPath 주석으로 UserID XML 요소의 콘텐츠를 사용자 메서드 매개 변수에 삽입합니다. 호출이 완료되면 반환 값이 Out 메시지의 본문에 삽입되고 경로의 다음 단계에 대해 In 메시지에 복사됩니다. 8080 Ref() 프로세서에서 빈 에 액세스하려면 Spring XML로 인스턴스를 인스턴스화해야 합니다. 예를 들어 META-INF/spring/camel-context.xml 구성 파일에 다음 행을 추가하여 Ignition을 인스턴스화할 수 있습니다.

<?xml version="1.0" encoding="UTF-8"?>
<beans ... >
  ...
  <bean id="bankBean" class="tutorial.BankBean"/>
</beans>

여기서 8080 ID, bankBean 에서는 레지스트리에 이 빈 인스턴스를 유휴 상태로 설정합니다.

빈 호출의 출력은 Velocity 템플릿에 삽입되어 올바르게 포맷된 결과 메시지를 생성합니다. Velocity 엔드포인트, speed :file:src/scripts/acc_balance.vm 에서는 다음 콘텐츠를 사용하여 속도 스크립트의 위치를 지정합니다.

<?xml version='1.0' encoding='UTF-8'?>
<Account>
  <BalanceResult>
    <UserID>${exchange.getProperty("userid")}</UserID>
    <Balance>${body}</Balance>
  </BalanceResult>
</Account>

교환 인스턴스는 ${ exchange.getProperty("userid")}를 사용하여 사용자 ID 교환 속성을 검색할 수 있는 Velocity 변수, exchange 로 사용할 수 있습니다. 현재 In 메시지( ${body} )의 본문에는 getUserAccBalance() 메서드 호출의 결과가 포함됩니다.

12장. System Management

초록

시스템 관리 패턴은 메시징 시스템을 모니터링, 테스트 및 관리하는 방법을 설명합니다.

12.1. detour

12.1.1. detour

3장. 엔터프라이즈 통합 패턴 소개 에서 Detour 를 사용하면 제어 조건이 충족되는 경우 추가 단계를 통해 메시지를 보낼 수 있습니다. 필요한 경우 추가 검증, 테스트, 디버깅 코드를 켜는 데 유용할 수 있습니다.

detour

12.1.2. 예제

이 예제에서는 기본적으로 경로 중간에 mock:detour 엔드포인트에 대한 조건부 detour와 함께 from("direct:start").to("mock:result") 와 같은 경로가 있습니다.

from("direct:start").choice()
    .when().method("controlBean", "isDetour").to("mock:detour").end()
    .to("mock:result");

Spring XML Extensions사용

<route>
  <from uri="direct:start"/>
    <choice>
      <when>
        <method bean="controlBean" method="isDetour"/>
	<to uri="mock:detour"/>
      </when>
    </choice>
    <to uri="mock:result"/>
  </split>
</route>

detour가 설정 또는 해제되었는지 여부는 ControlBean 에 의해 결정됩니다. 따라서 메시지에 detour가 라우팅되면 mock:detourmock:result. detour가 꺼져 있으면 메시지가 mock:result 로 라우팅됩니다.

자세한 내용은 여기에서 예제 소스를 확인하십시오.

camel-core/src/test/java/org/apache/camel/processor/DetourTest.java

12.2. LogEIP

12.2.1. 개요

Apache Camel은 경로에 로깅을 수행하는 여러 가지 방법을 제공합니다.

  • 로그 DSL 명령 사용.
  • 메시지 콘텐츠를 기록할 수 있는 로그 구성 요소를 사용합니다.
  • 메시지 흐름을 추적하는 추적기를 사용합니다.
  • Processor 또는 Cryostat 엔드포인트를 사용하여 Java 로그인을 수행합니다.
로그 DSL 명령과 로그 구성 요소 간의 차이점

로그 DSL은 훨씬 가벼우며 Starting to do …​ 과 같은 인적 로그를 로깅하기 위한 것입니다. 단순 언어를 기반으로 하는 메시지만 기록할 수 있습니다. 반대로 Log 구성 요소는 완전한 기능을 갖춘 로깅 구성 요소입니다. 로그 구성 요소는 메시지 자체를 로깅할 수 있으며 로깅을 제어하는 많은 URI 옵션이 있습니다.

12.2.2. Java DSL 예

Apache Camel 2.2 이므로 log DSL 명령을 사용하여 단순 표현식 언어를 사용하여 런타임에 로그 메시지를 구성할 수 있습니다. 예를 들어 다음과 같이 경로 내에 로그 메시지를 생성할 수 있습니다.

from("direct:start").log("Processing ${id}").to("bean:foo");

이 경로는 런타임에 문자열 형식 메시지를 생성합니다. 경로 ID를 로그 이름으로 사용하여 INFO 수준에 로그 메시지가 기록됩니다. 기본적으로 경로의 이름은 route-1,route -2 등입니다. 그러나 DSL 명령 routeId("myCoolRoute") 를 사용하여 사용자 지정 경로 ID를 지정할 수 있습니다.

또한 로그 DSL은 로깅 수준 및 로그 이름을 명시적으로 설정할 수 있는 변형을 제공합니다. 예를 들어 로깅 수준을 LoggingLevel.DEBUG 로 명시적으로 설정하려면 다음과 같이 로그 DSL을 호출할 수 있습니다.

로그 DSL에는 로깅 수준 및/또는 이름을 설정하는 오버로드된 방법이 있습니다.

from("direct:start").log(LoggingLevel.DEBUG, "Processing ${id}").to("bean:foo");

로그 이름을 fileRoute 로 설정하려면 다음과 같이 로그 DSL을 호출할 수 있습니다.

from("file://target/files").log(LoggingLevel.DEBUG, "fileRoute", "Processing file ${file:name}").to("bean:foo");

12.2.3. XML DSL 예

XML DSL에서 로그 DSL은 로그 요소로 표시되고 메시지 특성을 다음과 같이 단순 표현식으로 설정하여 로그 메시지가 지정됩니다.

<route id="foo">
    <from uri="direct:foo"/>
    <log message="Got ${body}"/>
    <to uri="mock:foo"/>
</route>

log 요소는 메시지,loggingLevellogName 특성을 지원합니다. 예를 들면 다음과 같습니다.

<route id="baz">
    <from uri="direct:baz"/>
    <log message="Me Got ${body}" loggingLevel="FATAL" logName="cool"/>
    <to uri="mock:baz"/>
</route>

12.2.4. 글로벌 로그 이름

경로 ID는 기본 로그 이름으로 사용됩니다. Apache Camel 2.17 부터 logname 매개변수를 구성하여 로그 이름을 변경할 수 있습니다.

Java DSL: 다음 예제를 기반으로 로그 이름을 구성합니다.

CamelContext context = ...
context.getProperties().put(Exchange.LOG_EIP_NAME, "com.foo.myapp");

XML에서 다음과 같은 방식으로 로그 이름을 구성합니다.

<camelContext ...>
  <properties>
    <property key="CamelLogEipName" value="com.foo.myapp"/>
  </properties>

로그가 두 개 이상 있고 모든 로그에 동일한 로그 이름을 사용하려면 각 로그에 구성을 추가해야 합니다.

12.3. Wire Tap

12.3.1. Wire Tap

그림 12.1. “Wire Tap 패턴” 에 표시된 유선 탭 패턴을 사용하면 원본 메시지가 최종 대상으로 전달되는 동안 메시지 사본을 별도의 탭 위치로 라우팅할 수 있습니다.

그림 12.1. Wire Tap 패턴

유선 탭
Streams

스트림 메시지 본문을 WireTap 하는 경우 스트림 캐싱 을 활성화하여 메시지 본문을 다시 읽을 수 있도록 해야 합니다. Stream Caching에서 자세한 내용을 참조하십시오.

12.3.2. triggertap 노드

Apache Camel 2.0은 유선 탭을 수행하기 위해 wireTap 노드를 도입했습니다. Tap 노드는 원본 교환을 단방향 스타일로 전파해야 하므로 교환 패턴이 InOnly 로 설정되어 있는 탭 교환으로 복사합니다. 탭된 교환은 기본 경로와 동시에 실행될 수 있도록 별도의 스레드에서 처리됩니다.

wireTap 은 교환을 활용하는 두 가지 방법을 지원합니다.

  • 원본 교환의 사본을 탭합니다.
  • 새 교환 인스턴스를 탭하여 탭된 교환을 사용자 지정할 수 있습니다.
참고

Camel 2.16에서 Wire Tap EIP는 원격 탭 대상으로 교환을 보낼 때 이벤트 알림을 발송합니다.

참고

Camel 2.20 부터는 닫는 동안 Wire Tap EIP가 작동 중단되는 모든 불광선 워킹을 완료합니다.

12.3.3. 원본 교환의 사본을 탭

Java DSL 사용:

from("direct:start")
    .to("log:foo")
    .wireTap("direct:tap")
    .to("mock:result");

Spring XML 확장 사용:

<route>
    <from uri="direct:start"/>
    <to uri="log:foo"/>
    <wireTap uri="direct:tap"/>
    <to uri="mock:result"/>
</route>

12.3.4. 원본 교환의 사본을 탭하고 수정

Apache Camel은 Java DSL을 사용하여 원래 교환의 복사본을 수정하는 프로세서 또는 표현식 사용을 지원합니다. 프로세서를 사용하면 속성, 헤더 등을 설정할 수 있으므로 교환이 채워지는 방식에 대한 전체 성능이 제공됩니다. 표현식 접근 방식은 In 메시지 본문을 수정하는 데만 사용할 수 있습니다.

예를 들어 프로세서 접근 방식을 사용하여 원래 교환의 사본을 수정하려면 다음을 수행합니다.

from("direct:start")
    .wireTap("direct:foo", new Processor() {
        public void process(Exchange exchange) throws Exception {
            exchange.getIn().setHeader("foo", "bar");
        }
    }).to("mock:result");

from("direct:foo").to("mock:foo");

그리고 표현식 접근 방식을 사용하여 원래 교환의 사본을 수정하려면 다음을 수행하십시오.

from("direct:start")
    .wireTap("direct:foo", constant("Bye World"))
    .to("mock:result");

from("direct:foo").to("mock:foo");

Spring XML 확장을 사용하여 프로세서 접근 방식을 사용하여 원래 교환의 복사본을 수정할 수 있습니다. 여기서 processorRef 속성은 myProcessor ID를 사용하여 Spring metrics을 참조합니다.

<route>
    <from uri="direct:start2"/>
    <wireTap uri="direct:foo" processorRef="myProcessor"/>
    <to uri="mock:result"/>
</route>

그리고 표현식 접근 방식을 사용하여 원래 교환의 사본을 수정하려면 다음을 수행하십시오.

<route>
    <from uri="direct:start"/>
    <wireTap uri="direct:foo">
        <body><constant>Bye World</constant></body>
    </wireTap>
    <to uri="mock:result"/>
</route>

12.3.5. 새 교환 인스턴스 탭

copy 플래그를 false 로 설정하여 새 교환 인스턴스로wiretap을 정의할 수 있습니다(기본값은 true). 이 경우wiretap에 대해 처음에 비어 있는 교환이 생성됩니다.

예를 들어 프로세서 접근 방식을 사용하여 새 교환 인스턴스를 생성하려면 다음을 수행합니다.

from("direct:start")
    .wireTap("direct:foo", false, new Processor() {
        public void process(Exchange exchange) throws Exception {
            exchange.getIn().setBody("Bye World");
            exchange.getIn().setHeader("foo", "bar");
        }
    }).to("mock:result");

from("direct:foo").to("mock:foo");

두 번째 wireTap 인수가 copy 플래그를 false 로 설정하여 원래 교환이 복사 되지 않고 대신 빈 교환이 생성됨을 나타냅니다.

표현식 접근 방식을 사용하여 새 교환 인스턴스를 생성하려면 다음을 수행합니다.

from("direct:start")
    .wireTap("direct:foo", false, constant("Bye World"))
    .to("mock:result");

from("direct:foo").to("mock:foo");

Spring XML 확장을 사용하면 wireTap 요소의 copy 속성을 false 로 설정하여 새 교환을 만들 것임을 나타낼 수 있습니다.

프로세서 접근 방식을 사용하여 새 교환 인스턴스를 생성하려면 다음과 같이 processorRef 속성이 myProcessor ID를 사용하여 Spring 빈을 참조합니다.

<route>
    <from uri="direct:start2"/>
    <wireTap uri="direct:foo" processorRef="myProcessor" copy="false"/>
    <to uri="mock:result"/>
</route>

그리고 표현식 접근 방식을 사용하여 새 교환 인스턴스를 생성하려면 다음을 수행합니다.

<route>
    <from uri="direct:start"/>
    <wireTap uri="direct:foo" copy="false">
        <body><constant>Bye World</constant></body>
    </wireTap>
    <to uri="mock:result"/>
</route>

12.3.6. 새 Exchange 전송 및 DSL에서 헤더 설정

Camel 2.8 사용 가능

12.3절. “Wire Tap” 를 사용하여 새 메시지를 보내는 경우 DSL의 II 부. 라우팅 표현식 및 서술자 언어 를 사용하여 메시지 본문만 설정할 수 있습니다. 새 헤더도 설정해야 하는 경우 1.5절. “프로세서” 를 사용해야 합니다. 따라서 Camel 2.8 이상에서 이 상황을 개선하여 DSL에서 헤더를 설정할 수 있습니다.

다음 예제에서는 다음과 같은 새 메시지를 보냅니다.

  • 메시지 본문으로 "bye World"
  • 값이 123인 키 "id"가 있는 헤더
  • 현재 날짜가 value인 키 "date"가 있는 헤더

12.3.7. Java DSL

from("direct:start")
     // tap a new message and send it to direct:tap
     // the new message should be Bye World with 2 headers
     .wireTap("direct:tap")
         // create the new tap message body and headers
         .newExchangeBody(constant("Bye World"))
         .newExchangeHeader("id", constant(123))
         .newExchangeHeader("date", simple("${date:now:yyyyMMdd}"))
     .end()
     // here we continue routing the original messages
     .to("mock:result");

 // this is the tapped route
 from("direct:tap")
     .to("mock:tap");

12.3.8. XML DSL

XML DSL은 메시지 본문 및 헤더를 구성하는 방법과 Java DSL과 약간 다릅니다. XML에서는 다음과 같이 <body> 및 <setHeader>를 사용합니다.

<route>
     <from uri="direct:start"/>
     <!-- tap a new message and send it to direct:tap -->
     <!-- the new message should be Bye World with 2 headers -->
     <wireTap uri="direct:tap">
         <!-- create the new tap message body and headers -->
         <body><constant>Bye World</constant></body>
         <setHeader headerName="id"><constant>123</constant></setHeader>
         <setHeader headerName="date"><simple>${date:now:yyyyMMdd}</simple></setHeader>
     </wireTap>
     <!-- here we continue routing the original message -->
     <to uri="mock:result"/>
 </route>

12.3.9. URI 사용

Wire Tap은 정적 및 동적 엔드 포인트 URI를 지원합니다. 정적 엔드포인트 URI는 Camel 2.20 부터 사용할 수 있습니다.

다음 예제에서는 헤더 ID가 큐 이름의 일부인 JMS 큐를 타이핑하는 방법을 표시합니다.

from("direct:start")
   .wireTap("jms:queue:backup-${header.id}")
   .to("bean:doSomething");

동적 끝점 URI에 대한 자세한 내용은 “동적 대상” 을 참조하십시오.

12.3.10. onPrepare를 사용하여 메시지를 준비할 때 사용자 정의 논리 실행

Camel 2.8 사용 가능

자세한 내용은 8.13절. “멀티 캐스트”의 내용을 참조하십시오.

12.3.11. 옵션

wireTap DSL 명령은 다음 옵션을 지원합니다.

이름

기본값

설명

uri

 

endpoint uri where to send thewire tapped message. uri 또는 ref 중 하나를 사용해야 합니다.

ref

 

전선 탭된 메시지를 보낼 끝점을 나타냅니다. uri 또는 ref 중 하나를 사용해야 합니다.

executorServiceRef

 

알 수 있는 메시지를 처리할 때 사용할 사용자 지정 2.8절. “스레드 모델” 을 나타냅니다. 설정되지 않은 경우 Camel은 기본 스레드 풀을 사용합니다.

processorRef

 

새 메시지를 생성하는 데 사용할 사용자 정의 1.5절. “프로세서”를 나타냅니다(예: 새 메시지 모드 전송). 아래를 참조하십시오.

복사

true

Camel 2.3: 메시지를 탭할 때 사용할 “교환” 복사본이 있어야 합니다.

onPrepareRef

 

Camel 2.8: “교환” 복사본을 준비하려면 사용자 지정 1.5절. “프로세서” 을 참조하십시오. 이를 통해 필요한 경우 메시지 페이로드를 깊이 복제하는 등 사용자 지정 논리를 수행할 수 있습니다.

II 부. 라우팅 표현식 및 서술자 언어

이 가이드에서는 Apache Camel에서 지원하는 평가 언어에서 사용하는 기본 구문을 설명합니다.

13장. 소개

초록

이 장에서는 Apache Camel에서 지원하는 모든 표현식 언어에 대한 개요를 제공합니다.

13.1. 언어 개요

13.1.1. 표현식 및 서술자 언어 표

표 13.1. “표현 및 사전 언어” 표현식 및 서술자 언어를 호출하는 데 사용되는 다양한 구문에 대한 개요를 제공합니다.

표 13.1. 표현 및 사전 언어

언어정적 메서드fluent DSL MethodXML 요소주석아티팩트

고객 포털의 Apache Camel 개발 가이드에서 Cryo stat 통합을 참조하십시오.

bean()

EIP().method()

method

@Bean

Camel 코어

14장. 상수

constant()

EIP().constant()

상수

@Constant

Camel 코어

15장. EL

el()

EIP().el()

el

@EL

camel-juel

17장. Groovy

groovy()

EIP().groovy()

groovy

@Groovy

camel-groovy

18장. 헤더

header()

EIP().header()

헤더

@Header

Camel 코어

19장. JavaScript

javaScript()

EIP().javaScript()

javaScript

@JavaScript

camel-script

20장. JoSQL

sql()

EIP().sql()

sql

@SQL

camel-josql

21장. JsonPath

없음

EIP().jsonpath()

jsonpath

@JsonPath

camel-jsonpath

22장. JXPath

없음

EIP().jxpath()

jxpath

@JXPath

camel-jxpath

23장. MVEL

mvel()

EIP().mvel()

MVEL

@MVEL

camel-mvel

24장. Object-Graph Navigation Language(OGNL)

ognl()

EIP().ognl()

ognl

@OGNL

camel-ognl

25장. PHP (더 이상 사용되지 않음)

php()

EIP().php()

php

@PHP

camel-script

26장. 자산 교환

property()

EIP().property()

속성

@Property

Camel 코어

27장. Python (DEPRECATED)

python()

EIP().python()

python

@Python

camel-script

28장. Ref

ref()

EIP().ref()

ref

해당 없음

Camel 코어

29장. Ruby (DEPRECATED)

ruby()

EIP().ruby()

ruby

@Ruby

camel-script

30장. 간단한 언어/16장. 파일 언어

simple()

EIP().simple()

단순

@Simple

Camel 코어

31장. SpEL

spel()

EIP().spel()

SPEL

@SpEL

camel-spring

32장. Cryostat 언어

xpath()

EIP().xpath()

xpath

@XPath

Camel 코어

33장. XQuery

xquery()

EIP().xquery()

xquery

@XQuery

camel-saxon

13.2. Expression Language를 사용하는 방법

13.2.1. 사전 요구 사항

특정 표현식 언어를 사용하려면 먼저 클래스 경로에서 필요한 JAR 파일을 사용할 수 있는지 확인해야 합니다. 사용하려는 언어가 Apache Camel 코어에 포함되어 있지 않은 경우 해당 JAR을 클래스 경로에 추가해야 합니다.

Maven 빌드 시스템을 사용하는 경우 POM 파일에 관련 종속성을 추가하여 build-time classpath를 수정할 수 있습니다. 예를 들어 Ruby 언어를 사용하려면 POM 파일에 다음 종속성을 추가합니다.

<dependency>
  <groupId>org.apache.camel</groupId>
  <artifactId>camel-groovy</artifactId>
  <!-- Use the same version as your Camel core version -->
  <version>${camel.version}</version>
</dependency>

Red Hat Fuse OSGi 컨테이너에 애플리케이션을 배포하려면 관련 언어 기능이 설치되어 있는지 확인해야 합니다(해당 Maven 아티팩트 뒤에 기능 이름이 지정됨). 예를 들어 OSGi 컨테이너에서 Groovy 언어를 사용하려면 먼저 다음 OSGi console 명령을 입력하여 camel-groovy 기능을 설치해야 합니다.

karaf@root> features:install camel-groovy
참고

경로에서 표현식 또는 서술자를 사용하는 경우 resource:classpath:path 또는 resource:file:path 를 사용하여 값을 외부 리소스로 참조합니다. 예를 들어 resource:classpath:com/foo/myscript.groovy.

13.2.2. Camel on EAP 배포

camel-groovy 구성 요소는 Red Hat JBoss EAP(JBoss Enterprise Application Platform) 컨테이너에 단순화된 배포 모델을 제공하는 EAP의 Camel(Wildfly Camel) 프레임워크에서 지원합니다.

13.2.3. 호출 방법

표 13.1. “표현 및 사전 언어” 에 표시된 대로 사용되는 컨텍스트에 따라 표현식 언어를 호출하는 데 사용되는 여러 가지 구문이 있습니다. 표현식 언어를 호출할 수 있습니다.

13.2.4. 정적 메서드로

대부분의 언어는 org.apache.camel.Expression 유형 또는 org.apache.camel.Predicate 유형이 예상되는 모든 컨텍스트에서 사용할 수 있는 정적 메서드를 정의합니다. 정적 메서드는 문자열 식(또는 조건자)을 인수로 사용하고 Expression 개체(일반적으로 Predicate 오브젝트)를 반환합니다.

예를 들어 XML 형식으로 메시지를 처리하는 콘텐츠 기반 라우터를 구현하려면 다음과 같이 /order/address/countryCode 요소의 값을 기반으로 메시지를 라우팅할 수 있습니다.

from("SourceURL")
  .choice
    .when(xpath("/order/address/countryCode = 'us'"))
      .to("file://countries/us/")
    .when(xpath("/order/address/countryCode = 'uk'"))
      .to("file://countries/uk/")
    .otherwise()
      .to("file://countries/other/")
  .to("TargetURL");

13.2.5. 유창한 DSL 방법

Java fluent DSL은 표현식 언어를 호출하는 다른 스타일을 지원합니다. EIP(Enterprise Integration Pattern)에 대한 인수로 표현식을 제공하는 대신 DSL 명령의 하위 규칙으로 표현식을 제공할 수 있습니다. 예를 들어, Cryostat 표현식을 filter(xpath("Expression") 로 호출하는 대신, filter().xpath("Expression") 로 표현식을 호출할 수 있습니다.

예를 들어 이전 콘텐츠 기반 라우터는 다음과 같이 이 호출 스타일로 다시 구현할 수 있습니다.

from("SourceURL")
  .choice
    .when().xpath("/order/address/countryCode = 'us'")
      .to("file://countries/us/")
    .when().xpath("/order/address/countryCode = 'uk'")
      .to("file://countries/uk/")
    .otherwise()
      .to("file://countries/other/")
  .to("TargetURL");

13.2.6. XML 요소

관련 XML 요소 내에 식 문자열을 배치하여 XML로 표현식 언어를 호출할 수도 있습니다.

예를 들어 XML에서 Cryostat를 호출하는 XML 요소는 (표준 Apache Camel 네임스페이스에 속하는) xpath 입니다. 다음과 같이 XML DSL 콘텐츠 기반 라우터에서 Cryostat 식을 사용할 수 있습니다.

<from uri="file://input/orders"/>
<choice>
  <when>
    <xpath>/order/address/countryCode = 'us'</xpath>
    <to uri="file://countries/us/"/>
  </when>
  <when>
    <xpath>/order/address/countryCode = 'uk'</xpath>
    <to uri="file://countries/uk/"/>
  </when>
  <otherwise>
    <to uri="file://countries/other/"/>
  </otherwise>
</choice>

또는 언어 특성에서 언어 이름을 지정하는 language 요소를 사용하여 언어 식을 지정할 수 있습니다.Alternatively, you can specify a language expression using the language element, where you specify the name of the language in the language attribute. 예를 들어 language 요소를 사용하여 다음과 같이 Cryostat 식을 정의할 수 있습니다.For example, you can define an Cryostat expression using the language element as follows:

<language language="xpath">/order/address/countryCode = 'us'</language>

13.2.7. 주석으로

언어 주석은 8080 통합 컨텍스트에서 사용됩니다. 주석은 메시지 또는 헤더에서 정보를 추출한 다음 추출된 데이터를 blank의 메서드 셰이프에 삽입하는 편리한 방법을 제공합니다.

예를 들어, 8080, myBeanProc 에서는 filter() EIP의 서술자로 호출됩니다. 8080의 checkCredentials 메서드가 true 를 반환하면 메시지는 계속 진행할 수 있지만 메서드에서 false 를 반환하는 경우 해당 메시지는 필터에 의해 차단됩니다. 필터 패턴은 다음과 같이 구현됩니다.

// Java
MyBeanProcessor myBeanProc = new MyBeanProcessor();

from("SourceURL")
  .filter().method(myBeanProc, "checkCredentials")
  .to("TargetURL");

MyBeanProcessor 클래스의 구현은 다음과 같이 @XPath 주석을 악용하여 기본 XML 메시지에서 사용자 이름과 암호를 추출합니다.

// Java
import org.apache.camel.language.XPath;

public class MyBeanProcessor {
    boolean void checkCredentials(
        @XPath("/credentials/username/text()") String user,
        @XPath("/credentials/password/text()") String pass
    ) {
        // Check the user/pass credentials...
        ...
    }
}

@XPath 주석은 삽입되는 매개변수 바로 앞에 배치됩니다. path에 /text() 를 추가하여 명시적으로 텍스트 노드를 선택하는 방법을 확인할 수 있습니다. 이렇게 하면 요소의 콘텐츠만 enclosing 태그가 아닌 선택되어 있는지 확인합니다.

13.2.8. Camel 엔드 포인트 URI로 사용

Camel Language 구성 요소를 사용하여 엔드포인트 URI에서 지원되는 언어를 호출할 수 있습니다. 두 가지 대체 구문이 있습니다.

파일(또는 Scheme)에 저장된 언어 스크립트를 호출하려면 다음 URI 구문을 사용합니다.

language://LanguageName:resource:Scheme:Location[?Options]

여기서 스키마는 파일(, classpath: 또는 http: )일 수 있습니다.

예를 들어 다음 경로는 classpath에서 mysimplescript.txt 를 실행합니다.

from("direct:start")
  .to("language:simple:classpath:org/apache/camel/component/language/mysimplescript.txt")
  .to("mock:result");

포함된 언어 스크립트를 호출하려면 다음 URI 구문을 사용합니다.

language://LanguageName[:Script][?Options]

예를 들어 스크립트 문자열에 저장된 단순 언어 스크립트를 실행하려면 다음을 수행합니다.

String script = URLEncoder.encode("Hello ${body}", "UTF-8");
from("direct:start")
  .to("language:simple:" + script)
  .to("mock:result");

언어 구성 요소에 대한 자세한 내용은 Apache Camel 구성 요소 참조 가이드의 언어 를 참조하십시오.

14장. 상수

14.1. 개요

상수 언어는 일반 텍스트 문자열을 지정하는 데 사용되는 간단한 기본 제공 언어입니다. 이렇게 하면 표현식 유형이 예상되는 모든 컨텍스트에서 일반 텍스트 문자열을 제공할 수 있습니다.

14.2. XML 예

XML에서 username 헤더를 다음과 같이 값 Jane Doe 으로 설정할 수 있습니다.

<camelContext>
  <route>
    <from uri="SourceURL"/>
    <setHeader headerName="username">
      <constant>Jane Doe</constant>
    </setHeader>
    <to uri="TargetURL"/>
  </route>
</camelContext>

14.3. Java 예

Java에서는 다음과 같이 username 헤더를 값 Jane Doe 으로 설정할 수 있습니다.

from("SourceURL")
  .setHeader("username", constant("Jane Doe"))
  .to("TargetURL");

15장. EL

15.1. 개요

EL(Unified Expression Language)은 원래 JSP 2.1 표준(JSR-245)의 일부로 지정되었지만 이제 독립 실행형 언어로 사용할 수 있습니다. Apache Camel은 EL 언어의 오픈 소스 구현인 JUEL( http://juel.sourceforge.net/)과 통합됩니다.http://juel.sourceforge.net/

15.2. JUEL 패키지 추가

경로에서 EL을 사용하려면 예 15.1. “camel-juel 종속성 추가” 에 표시된 대로 camel-juel 에 대한 종속성을 프로젝트에 추가해야 합니다.

예 15.1. camel-juel 종속성 추가

<!-- Maven POM File -->
<properties>
  <camel-version>2.23.2.fuse-790054-redhat-00001</camel-version>
  ...
</properties>

<dependencies>
  ...
  <dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-juel</artifactId>
    <version>${camel-version}</version>
  </dependency>
  ...
</dependencies>

15.3. 정적 가져오기

애플리케이션 코드에서 el() 정적 메서드를 사용하려면 Java 소스 파일에 다음 import 문을 포함합니다.

import static org.apache.camel.language.juel.JuelExpression.el;

15.4. 변수

표 15.1. “EL 변수” EL을 사용할 때 액세스할 수 있는 변수를 나열합니다.

표 15.1. EL 변수

Variable유형현재의

exchange

org.apache.camel.Exchange

현재 교환

in

org.apache.camel.Message

IN 메시지

out

org.apache.camel.Message

OUT 메시지

15.5. 예제

예 15.2. “EL을 사용하는 경로” EL을 사용하는 두 개의 경로를 보여줍니다.

예 15.2. EL을 사용하는 경로

<camelContext>
  <route>
    <from uri="seda:foo"/>
    <filter>
      <language language="el">${in.headers.foo == 'bar'}</language>
      <to uri="seda:bar"/>
    </filter>
  </route>
  <route>
    <from uri="seda:foo2"/>
    <filter>
      <language language="el">${in.headers['My Header'] == 'bar'}</language>
      <to uri="seda:bar"/>
    </filter>
  </route>
</camelContext>

16장. 파일 언어

초록

파일 언어는 단순한 언어의 확장이며, 그 자체로 독립적인 언어가 아닙니다. 그러나 파일 언어 확장은 파일 또는 FTP 끝점과 함께만 사용할 수 있습니다.

16.1. 파일 언어를 사용해야 하는 경우

16.1.1. 개요

파일 언어는 항상 사용할 수 있는 간단한 언어의 확장입니다. 다음과 같은 상황에서 사용할 수 있습니다.

참고

이스케이프 문자 \ 는 파일 언어로 사용할 수 없습니다.

16.1.2. 파일 또는 FTP 소비자 끝점에서

File 또는 FTP 소비자 끝점에 설정할 수 있는 여러 URI 옵션이 있으며, 이는 파일 언어 표현식을 값으로 사용합니다. 예를 들어 File consumer endpoint URI에서 fileName,move,pre Cryostat ,moveFailed, sortBy 옵션을 설정할 수 있습니다.

파일 소비자 끝점에서 fileName 옵션은 필터 역할을 하며 시작 디렉터리에서 실제로 읽을 파일을 결정합니다. 일반 텍스트 문자열이 지정된 경우(예: fileName=report.txt) 파일 소비자는 업데이트할 때마다 동일한 파일을 읽습니다. 그러나 간단한 표현식을 지정하면 이 옵션을 더 동적으로 만들 수 있습니다. 예를 들어 다음과 같이 파일 소비자가 시작 디렉터리를 폴링할 때마다 카운터 8080을 사용하여 다른 파일을 선택할 수 있습니다.

file://target/filelanguage/bean/?fileName=${bean:counter.next}.txt&delete=true

여기서 ${bean:counter.next} 표현식은 ID, 카운터 아래에 등록된 metrics에서 next() 메서드를 호출합니다.

move 옵션은 File consumer endpoint에서 읽은 후 백업 위치로 파일을 이동하는 데 사용됩니다. 예를 들어 다음 끝점은 파일을 처리한 후 백업 디렉터리로 이동합니다.

file://target/filelanguage/?move=backup/${date:now:yyyyMMdd}/${file:name.noext}.bak&recursive=false

여기서 ${file:name.noext}.bak 표현식은 원래 파일 이름을 수정하여 파일 확장자를 .bak 로 바꿉니다.

sortBy 옵션을 사용하여 파일을 처리해야 하는 순서를 지정할 수 있습니다. 예를 들어 파일 이름의 알파벳 순서에 따라 파일을 처리하려면 다음 파일 소비자 끝점을 사용할 수 있습니다.

file://target/filelanguage/?sortBy=file:name

마지막으로 수정된 순서에 따라 파일을 처리하려면 다음 파일 소비자 끝점을 사용할 수 있습니다.

file://target/filelanguage/?sortBy=file:modified

다음과 같이 reverse: prefix Cryostat- Cryostat를 추가하여 순서를 취소할 수 있습니다.

file://target/filelanguage/?sortBy=reverse:file:modified

16.1.3. 파일 또는 FTP 소비자가 만든 교환 시

File 또는 FTP 소비자 끝점에서 교환이 시작되면 경로 전체의 교환에 파일 언어 표현식을 적용할 수 있습니다(원래 메시지 헤더가 삭제되지 않는 한). 예를 들어 다음과 같이 파일 확장자에 따라 메시지를 라우팅하는 콘텐츠 기반 라우터를 정의할 수 있습니다.

<from uri="file://input/orders"/>
<choice>
  <when>
    <simple>${file:ext} == 'txt'</simple>
    <to uri="bean:orderService?method=handleTextFiles"/>
  </when>
  <when>
    <simple>${file:ext} == 'xml'</simple>
    <to uri="bean:orderService?method=handleXmlFiles"/>
  </when>
  <otherwise>
    <to uri="bean:orderService?method=handleOtherFiles"/>
  </otherwise>
</choice>

16.2. 파일 변수

16.2.1. 개요

파일 변수는 파일 또는 FTP 소비자 엔드포인트로 시작할 때마다 사용할 수 있으며, 이는 기본 메시지 본문이 java.io.File 유형임을 의미합니다. 파일 변수를 사용하면 java.io.File 클래스의 메서드를 호출하는 것처럼 파일 경로 이름의 다양한 부분에 액세스할 수 있습니다(실제로 파일 또는 FTP 엔드포인트에서 설정한 메시지 헤더에서 필요한 정보를 추출함).

16.2.2. 시작 디렉터리

일부 파일 변수는 시작 디렉터리 에 대해 정의된 경로를 반환하며 이는 파일 또는 FTP 끝점에 지정된 디렉터리일 뿐입니다. 예를 들어 다음 파일 소비자 끝점에는 시작 디렉터리 ./filetransfer ( 상대 경로)가 있습니다.

file:filetransfer

다음 FTP 소비자 끝점에는 시작 디렉터리 ./ftptransfer ( 상대 경로)가 있습니다.

ftp://myhost:2100/ftptransfer

16.2.3. 파일 변수 이름 지정

일반적으로 파일 변수는 java.io.File 클래스에서 해당 메서드 뒤에 이름이 지정됩니다. 예를 들어 file:absolute 변수는 java.io.File.getAbsolute() 메서드에서 반환하는 값을 제공합니다.

참고

그러나 이 명명 규칙은 엄격하게 따르지 않습니다. 예를 들어 java.io.File.getSize() 와 같은 메서드는 없습니다.

16.2.4. 변수 테이블

표 16.1. “파일 언어의 변수” 파일 언어에서 지원하는 모든 변수를 표시합니다.

표 16.1. 파일 언어의 변수

Variable유형설명

file:name

문자열

시작 디렉터리를 기준으로 하는 경로 이름입니다.

file:name.ext

문자열

파일 확장자( pathname의 마지막 . 문자 다음에 있는 문자). 여러 점이 있는 파일 확장자를 지원합니다(예: .tar.gz ).

file:name.ext.single

문자열

파일 확장자( pathname의 마지막 . 문자 다음에 있는 문자). 파일 확장에 mutiple 점이 있는 경우 이 표현식은 마지막 부분만 반환합니다.

file:name.noext

문자열

시작 디렉터리를 기준으로 파일 확장자를 생략하는 경로 이름입니다.

file:name.noext.single

문자열

시작 디렉터리를 기준으로 파일 확장자를 생략하는 경로 이름입니다. 파일 확장에 점이 여러 개 있는 경우 이 표현식은 마지막 부분만 제거하고 나머지 부분을 유지합니다.

file:onlyname

문자열

경로 이름의 마지막 세그먼트입니다. 즉, 상위 디렉터리 경로가 없는 파일 이름입니다.

file:onlyname.noext

문자열

경로 이름의 마지막 세그먼트로, 파일 확장자를 생략합니다.

file:onlyname.noext.single

문자열

경로 이름의 마지막 세그먼트로, 파일 확장자를 생략합니다. 파일 확장에 점이 여러 개 있는 경우 이 표현식은 마지막 부분만 제거하고 나머지 부분을 유지합니다.

file:ext

문자열

파일 확장자( file:name.ext와 동일)

file:parent

문자열

경로에 시작 디렉터리를 포함하여 상위 디렉터리의 경로 이름입니다.

file:path

문자열

경로의 시작 디렉터리를 포함한 파일 경로 이름입니다.

file:absolute

부울

true, 시작 디렉터리가 절대 경로로 지정되면 false , 그렇지 않으면 false 입니다.

file:absolute.path

문자열

파일의 절대 경로 이름입니다.

file:length

long

참조된 파일의 크기입니다.

file:size

long

file:length 과 동일합니다.

file:modified

java.util.Date

마지막으로 수정된 날짜입니다.

16.3. 예

16.3.1. 상대 경로 이름

시작 디렉터리가 상대 경로 이름으로 지정된 파일 소비자 끝점을 고려합니다. 예를 들어 다음 File 끝점에는 시작 디렉터리 ./file language:

file://filelanguage

이제 파일 language 디렉토리를 스캔하는 동안 끝점이 다음 파일을 사용했다고 가정합니다.

./filelanguage/test/hello.txt

마지막으로 파일 language 디렉터리 자체에 다음과 같은 절대 위치가 있다고 가정합니다.

/workspace/camel/camel-core/target/filelanguage

이전 시나리오에서 파일 언어 변수는 현재 교환에 적용할 때 다음 값을 반환합니다.

expression결과

file:name

test/hello.txt

file:name.ext

txt

file:name.noext

test/hello

file:onlyname

hello.txt

file:onlyname.noext

안녕하세요

file:ext

txt

file:parent

filelanguage/test

file:path

filelanguage/test/hello.txt

file:absolute

false

file:absolute.path

/workspace/camel/camel-core/target/filelanguage/test/hello.txt

16.3.2. 절대 경로 이름

시작 디렉터리가 절대 경로 이름으로 지정된 파일 소비자 끝점을 고려합니다. 예를 들어 다음 File 끝점에는 시작 디렉터리 /workspace/camel/camel-core/target/file language 가 있습니다.

file:///workspace/camel/camel-core/target/filelanguage

이제 파일 language 디렉토리를 스캔하는 동안 끝점이 다음 파일을 사용했다고 가정합니다.

./filelanguage/test/hello.txt

이전 시나리오에서 파일 언어 변수는 현재 교환에 적용할 때 다음 값을 반환합니다.

expression결과

file:name

test/hello.txt

file:name.ext

txt

file:name.noext

test/hello

file:onlyname

hello.txt

file:onlyname.noext

안녕하세요

file:ext

txt

file:parent

/workspace/camel/camel-core/target/filelanguage/test

file:path

/workspace/camel/camel-core/target/filelanguage/test/hello.txt

file:absolute

true

file:absolute.path

/workspace/camel/camel-core/target/filelanguage/test/hello.txt

17장. Groovy

17.1. 개요

Groovy는 오브젝트를 빠르게 구문 분석할 수 있는 Java 기반 스크립팅 언어입니다. Groovy 지원은 camel-groovy 모듈의 일부입니다.

17.2. script 모듈 추가

경로에서 Groovy를 사용하려면 예 17.1. “camel-groovy 종속성 추가” 과 같이 camel-groovy 에 대한 종속 항목을 프로젝트에 추가해야 합니다.

예 17.1. camel-groovy 종속성 추가

<!-- Maven POM File -->
<properties>
  <camel-version>2.23.2.fuse-790054-redhat-00001</camel-version>
  ...
</properties>

<dependencies>
  ...
  <dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-groovy</artifactId>
    <version>${camel-version}</version>
  </dependency>
</dependencies>

17.3. 정적 가져오기

애플리케이션 코드에서 groovy() 정적 메서드를 사용하려면 Java 소스 파일에 다음 import 문을 포함합니다.

import static org.apache.camel.builder.script.ScriptBuilder.*;

17.4. 기본 제공 속성

표 17.1. “groovy 속성” Groovy를 사용할 때 액세스할 수 있는 기본 제공 속성을 나열합니다.

표 17.1. groovy 속성

속성유형현재의

context

org.apache.camel.CamelContext

Camel 컨텍스트

exchange

org.apache.camel.Exchange

현재 교환

request

org.apache.camel.Message

IN 메시지

응답

org.apache.camel.Message

OUT 메시지

속성

org.apache.camel.builder.script.PropertiesFunction

확인 방법과 함께 작동하여 스크립트 내에서 속성 구성 요소를 더 쉽게 사용할 수 있습니다.

ENGINE_SCOPE 에서 모두 설정된 속성입니다.

17.5. 예제

예 17.2. “Groovy를 사용하는 경로” Groovy 스크립트를 사용하는 두 개의 경로를 보여줍니다.

예 17.2. Groovy를 사용하는 경로

<camelContext>
  <route>
    <from uri="direct:items" />
    <filter>
      <language language="groovy">request.lineItems.any { i -> i.value > 100 }</language>
      <to uri="mock:mock1" />
    </filter>
  </route>
  <route>
    <from uri="direct:in"/>
    <setHeader headerName="firstName">
      <language language="groovy">$user.firstName $user.lastName</language>
    </setHeader>
    <to uri="seda:users"/>
  </route>
</camelContext>

17.6. 속성 구성 요소 사용

속성 구성 요소에서 속성 값에 액세스하려면 다음과 같이 기본 제공 속성 속성에서 resolve 메서드를 호출합니다.To access a property value from the properties component, invoke the resolve method on the built-in properties attribute, as follows:

.setHeader("myHeader").groovy("properties.resolve(PropKey)")

여기서 PropKey 는 확인하려는 속성의 키이며 키 값은 String 유형의 키입니다.

속성 구성 요소에 대한 자세한 내용은 Apache Camel 구성 요소 참조 가이드의 속성을 참조하십시오.https://access.redhat.com/documentation/en-us/red_hat_fuse/7.9/html-single/apache_camel_component_reference/index#properties-component

17.7. Groovy Shell 사용자 정의

경우에 따라 사용자 지정 GroovyShell 인스턴스를 Groovy 표현식에서 사용해야 할 수도 있습니다. 사용자 정의 GroovyShell 을 제공하려면 org.apache.camel. Cryostat.groovy.GroovyShell SPI 인터페이스를 Camel 레지스트리에 추가합니다.

예를 들어, Spring 컨텍스트에 다음 8080을 추가하면 Apache Camel은 기본 정적 가져오기 대신 사용자 지정 정적 가져오기를 포함하는 사용자 지정 GroovyShell 인스턴스를 사용합니다.

public class CustomGroovyShellFactory implements GroovyShellFactory {

  public GroovyShell createGroovyShell(Exchange exchange) {
    ImportCustomizer importCustomizer = new ImportCustomizer();
    importCustomizer.addStaticStars("com.example.Utils");
    CompilerConfiguration configuration = new CompilerConfiguration();
    configuration.addCompilationCustomizers(importCustomizer);
    return new GroovyShell(configuration);
  }
 }

19장. JavaScript

19.1. 개요

ECMAScript라고도 하는 JavaScript는 오브젝트를 빠르게 구문 분석할 수 있는 Java 기반 스크립팅 언어입니다. JavaScript 지원은 camel-script 모듈의 일부입니다.

19.2. script 모듈 추가

경로에서 JavaScript를 사용하려면 예 19.1. “camel-script 종속성 추가” 에 표시된 대로 camel-script 에 대한 종속성을 프로젝트에 추가해야 합니다.

예 19.1. camel-script 종속성 추가

<!-- Maven POM File -->
<properties>
  <camel-version>2.23.2.fuse-790054-redhat-00001</camel-version>
  ...
</properties>

<dependencies>
  ...
  <dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-script</artifactId>
    <version>${camel-version}</version>
  </dependency>
  ...
</dependencies>

19.3. 정적 가져오기

애플리케이션 코드에서 javaScript() 정적 메서드를 사용하려면 Java 소스 파일에 다음 import 문을 포함합니다.

import static org.apache.camel.builder.script.ScriptBuilder.*;

19.4. 기본 제공 속성

표 19.1. “JavaScript 속성” JavaScript를 사용할 때 액세스할 수 있는 기본 제공 속성을 나열합니다.

표 19.1. JavaScript 속성

속성유형현재의

context

org.apache.camel.CamelContext

Camel 컨텍스트

exchange

org.apache.camel.Exchange

현재 교환

request

org.apache.camel.Message

IN 메시지

응답

org.apache.camel.Message

OUT 메시지

속성

org.apache.camel.builder.script.PropertiesFunction

확인 방법과 함께 작동하여 스크립트 내에서 속성 구성 요소를 더 쉽게 사용할 수 있습니다.

ENGINE_SCOPE 에서 모두 설정된 속성입니다.

19.5. 예제

예 19.2. “JavaScript를 사용하는 경로” JavaScript를 사용하는 경로를 표시합니다.

예 19.2. JavaScript를 사용하는 경로

<camelContext>
  <route>
    <from uri="direct:start"/>
    <choice>
      <when>
        <langauge langauge="javaScript">request.headers.get('user') == 'admin'</langauge>
        <to uri="seda:adminQueue"/>
      </when>
      <otherwise>
        <to uri="seda:regularQueue"/>
      </otherwise>
    </choice>
  </route>
</camelContext>

19.6. 속성 구성 요소 사용

속성 구성 요소에서 속성 값에 액세스하려면 다음과 같이 기본 제공 속성 속성에서 resolve 메서드를 호출합니다.To access a property value from the properties component, invoke the resolve method on the built-in properties attribute, as follows:

.setHeader("myHeader").javaScript("properties.resolve(PropKey)")

여기서 PropKey 는 확인하려는 속성의 키이며 키 값은 String 유형의 키입니다.

속성 구성 요소에 대한 자세한 내용은 Apache Camel 구성 요소 참조 가이드의 속성을 참조하십시오.https://access.redhat.com/documentation/en-us/red_hat_fuse/7.9/html-single/apache_camel_component_reference/index#properties-component

20장. JoSQL

20.1. 개요

JoSQL(Java 개체용 SQL) 언어를 사용하면 Apache Camel에서 서술자 및 표현식을 평가할 수 있습니다. JoSQL은 SQL과 같은 쿼리 구문을 사용하여 메모리 내 Java 개체의 데이터에 대한 선택 및 순서 지정 작업을 수행합니다. JoSQL은 데이터베이스가 아닙니다. JoSQL 구문에서 각 Java 개체 인스턴스는 테이블 행처럼 취급되며 각 개체 메서드는 열 이름처럼 처리됩니다. 이 구문을 사용하면 Java 개체 컬렉션에서 데이터를 추출하고 컴파일하기 위한 강력한 문을 구성할 수 있습니다. 자세한 내용은 http://josql.sourceforge.net/ 을 참조하십시오.

20.2. JoSQL 모듈 추가

경로에서 JoSQL을 사용하려면 예 20.1. “camel-josql 종속성 추가” 과 같이 camel-josql 에 대한 종속성을 프로젝트에 추가해야 합니다.

예 20.1. camel-josql 종속성 추가

<!-- Maven POM File -->
...
<dependencies>
  ...
  <dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-josql</artifactId>
    <version>${camel-version}</version>
  </dependency>
  ...
</dependencies>

20.3. 정적 가져오기

애플리케이션 코드에서 sql() 정적 메서드를 사용하려면 Java 소스 파일에 다음 import 문을 포함합니다.

import static org.apache.camel.builder.sql.SqlBuilder.sql;

20.4. 변수

표 20.1. “SQL 변수” JoSQL을 사용할 때 액세스할 수 있는 변수를 나열합니다.

표 20.1. SQL 변수

이름유형설명

exchange

org.apache.camel.Exchange

현재 교환

in

org.apache.camel.Message

IN 메시지

out

org.apache.camel.Message

OUT 메시지

속성

개체

키가 속성인 교환 속성

헤더

개체

키가 헤더인 IN 메시지 헤더

variable

개체

키가 변수인 변수

20.5. 예제

예 20.2. “JoSQL을 사용하는 경로” JoSQL을 사용하는 경로를 표시합니다.

예 20.2. JoSQL을 사용하는 경로

<camelContext>
  <route>
    <from uri="direct:start"/>
    <setBody>
      <language language="sql">select * from MyType</language>
    </setBody>
    <to uri="seda:regularQueue"/>
  </route>
</camelContext>

21장. JsonPath

21.1. 개요

JsonPath 언어는 JSON 메시지의 일부를 추출하기 위한 편리한 구문을 제공합니다. JSON 구문은 Cryostat와 유사하지만 XML에서 작동하는 대신 JSON 메시지에서 JSON 오브젝트를 추출하는 데 사용됩니다. jsonpath DSL 명령은 표현식 또는 서술자로 사용할 수 있습니다(이 경우 빈 결과가 부울 false로 해석됨).

21.2. JsonPath 패키지 추가

Camel 경로에서 JsonPath를 사용하려면 다음과 같이 camel-jsonpath 에 대한 종속성을 프로젝트에 추가해야 합니다.

<dependency>
  <groupId>org.apache.camel</groupId>
  <artifactId>camel-jsonpath</artifactId>
  <version>${camel-version}</version>
</dependency>

21.3. Java 예

다음 Java 예제에서는 jsonpath() DSL 명령을 사용하여 특정 가격 범위에서 항목을 선택하는 방법을 보여줍니다.

from("queue:books.new")
  .choice()
    .when().jsonpath("$.store.book[?(@.price < 10)]")
      .to("jms:queue:book.cheap")
    .when().jsonpath("$.store.book[?(@.price < 30)]")
      .to("jms:queue:book.average")
    .otherwise()
      .to("jms:queue:book.expensive")

JsonPath 쿼리에서 빈 세트를 반환하는 경우 결과가 false 로 해석됩니다. 이렇게 하면 JsonPath 쿼리를 서술자로 사용할 수 있습니다.

21.4. XML 예

다음 XML 예제에서는 jsonpath DSL 요소를 사용하여 경로에 서술자를 정의하는 방법을 보여줍니다.

<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
  <route>
    <from uri="direct:start"/>
    <choice>
      <when>
        <jsonpath>$.store.book[?(@.price < 10)]</jsonpath>
        <to uri="mock:cheap"/>
      </when>
      <when>
        <jsonpath>$.store.book[?(@.price < 30)]</jsonpath>
        <to uri="mock:average"/>
      </when>
      <otherwise>
        <to uri="mock:expensive"/>
      </otherwise>
    </choice>
  </route>
</camelContext>

21.5. 쉬운 구문

jsonpath 구문을 사용하여 기본 서술자를 정의하려는 경우 구문을 기억하는 것이 다소 어려울 수 있습니다. 예를 들어 모든 저렴한 서적을 찾으려면 다음과 같이 구문을 작성해야 합니다.

$.store.book[?(@.price < 20)]

그러나 다음과 같이 작성할 수 있는 경우 어떻게 해야 합니까?

store.book.price < 20

price 키가 있는 노드를 확인하려는 경우 경로를 생략할 수도 있습니다.

price < 20

이를 지원하기 위해 기본 스타일을 사용하여 서술자를 정의하는 데 사용하는 easyPredicateParser 가 있습니다. 즉, 서술자는 $ 기호로 시작하지 않아야 하며 하나의 연산자만 포함해야 합니다. 쉬운 구문은 다음과 같습니다.

left OP right

올바른 Operator에서 Camel 간단한 언어를 사용할 수 있습니다. 예를 들면 다음과 같습니다.

store.book.price < ${header.limit}

21.6. 지원되는 메시지 본문 유형

Camel JSonPath는 다음 유형을 사용하여 메시지 본문을 지원합니다.

유형설명

파일

파일에서 읽기

문자열

일반 문자열

map

essage body as java.util.Map 유형

list

Message body as java.util.List 유형

POJO

jackson이 classpath에 있는 경우 camel-jsonpath 는 jackson을 사용하여 메시지 본문을 Cryostat로 읽고 JSonPath에서 지원하는 java.util.Map 으로 변환할 수 있습니다. 예를 들어 jackson을 포함하기 위해 camel-jackson 을 종속성으로 추가할 수 있습니다.

InputStream

위의 유형이 일치하지 않는 경우 Camel은 메시지 본문을 java.io.InputStream 으로 읽으려고 합니다.

메시지 본문이 지원되지 않는 형식인 경우 기본적으로 예외가 발생하지만 JSonPath를 구성하여 예외를 억제할 수 있습니다.

21.7. 예외 비활성화

jsonpath 표현식에서 구성한 경로를 찾을 수 없는 경우 JSONPath가 예외를 throw합니다. SuppressExceptions 옵션을 true로 설정하여 예외를 무시할 수 있습니다. 예를 들어 아래 코드에서 jsonpath 매개변수의 일부로 true 옵션을 추가합니다.

from("direct:start")
    .choice()
        // use true to suppress exceptions
        .when().jsonpath("person.middlename", true)
            .to("mock:middle")
        .otherwise()
            .to("mock:other");

XML DSL에서 다음 구문을 사용합니다.

<route>
  <from uri="direct:start"/>
  <choice>
    <when>
      <jsonpath suppressExceptions="true">person.middlename</jsonpath>
      <to uri="mock:middle"/>
    </when>
    <otherwise>
      <to uri="mock:other"/>
    </otherwise>
  </choice>
</route>

21.8. JSONPath 삽입

Cryostat 통합을 사용하여 Quarkus 메서드를 호출할 때 JsonPath를 사용하여 메시지에서 값을 추출하고 메서드 매개 변수에 바인딩할 수 있습니다. 예를 들면 다음과 같습니다.

// Java
public class Foo {

    @Consume(uri = "activemq:queue:books.new")
    public void doSomething(@JsonPath("$.store.book[*].author") String author, @Body String json) {
      // process the inbound message here
    }
}

21.9. 인라인 간단한 표현식

Camel 2.18의 새로운 기능.

Camel은 JsonPath 표현식에서 인라인 단순 표현식을 지원합니다. 간단한 언어 삽입은 다음과 같이 간단한 구문으로 표현해야 합니다.

from("direct:start")
  .choice()
    .when().jsonpath("$.store.book[?(@.price < `${header.cheap}`)]")
      .to("mock:cheap")
    .when().jsonpath("$.store.book[?(@.price < `${header.average}`)]")
      .to("mock:average")
    .otherwise()
      .to("mock:expensive");

아래 표시된 대로 allow Simple =false 옵션을 설정하여 단순 표현식에 대한 지원을 끕니다.

Java:

// Java DSL
.when().jsonpath("$.store.book[?(@.price < 10)]", false, false)

XML DSL:

// XML DSL
<jsonpath allowSimple="false">$.store.book[?(@.price &lt; 10)]</jsonpath>

21.10. reference

JsonPath에 대한 자세한 내용은 JSonPath 프로젝트 페이지를 참조하십시오.

22장. JXPath

22.1. 개요

JXPath 언어를 사용하면 Apache Commons JXPath 언어를 사용하여 Java 빈을 호출할 수 있습니다. JXPath 언어의 구문은 Cryostat와 유사하지만 XML 문서에서 요소 또는 특성 노드를 선택하는 대신 Java 빈 개체 그래프에서 메서드를 호출합니다. 빈 속성 중 하나가 XML 문서(^1/JDOM 인스턴스)를 반환하는 경우 경로의 나머지 부분은 Cryostat 표현식으로 해석되고 문서에서 XML 노드를 추출하는 데 사용됩니다. 즉, JXPath 언어는 개체 그래프 탐색 및 XML 노드 선택의 하이브리드를 제공합니다.

22.2. JXPath 패키지 추가

경로에서 JXPath를 사용하려면 예 22.1. “camel-jxpath 종속성 추가” 에 표시된 것처럼 camel-jxpath 에 대한 종속성을 프로젝트에 추가해야 합니다.

예 22.1. camel-jxpath 종속성 추가

<!-- Maven POM File -->
<properties>
  <camel-version>2.23.2.fuse-790054-redhat-00001</camel-version>
  ...
</properties>

<dependencies>
  ...
  <dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-jxpath</artifactId>
    <version>${camel-version}</version>
  </dependency>
  ...
</dependencies>

22.3. 변수

표 22.1. “JXPath 변수” JXPath를 사용할 때 액세스할 수 있는 변수를 나열합니다.

표 22.1. JXPath 변수

Variable유형현재의

org.apache.camel.Exchange

현재 교환

in

org.apache.camel.Message

IN 메시지

out

org.apache.camel.Message

OUT 메시지

22.4. 옵션

표 22.2. “JXPath 옵션” JXPath 옵션에 대해 설명합니다.

표 22.2. JXPath 옵션

옵션유형설명

lenient

boolean

Camel 2.11/2.10.5: JXPathContext를 설정할 수 있습니다. 이 옵션을 사용하면 JXPath 표현식이 잘못된 데이터 또는 누락될 수 있는 표현식 및 메시지 본문에 대해 평가할 수 있습니다. 자세한 내용은 JXPath 문서를 참조하십시오. 이 옵션은 기본적으로 false입니다.

22.5. 예

다음 예제 경로는 JXPath를 사용합니다.

<camelContext>
  <route>
    <from uri="activemq:MyQueue"/>
    <filter>
      <jxpath>in/body/name = 'James'</xpath>
      <to uri="mqseries:SomeOtherQueue"/>
    </filter>
  </route>
</camelContext>

다음 간단한 예제에서는 JXPath 표현식을 메시지 필터에서 서술자로 사용합니다.

from("direct:start").
    filter().jxpath("in/body/name='James'").
    to("mock:result");

22.6. JXPath 삽입

Cryostat 통합을 사용하여 8080에서 메서드를 호출하고 JXPath와 같은 다양한 언어를 사용하여 메시지에서 값을 추출하고 메서드 매개 변수에 바인딩할 수 있습니다.

예를 들면 다음과 같습니다.

public class Foo {
     @MessageDriven(uri = "activemq:my.queue")
     public void doSomething(@JXPath("in/body/foo") String correlationID, @Body String body)
     { // process the inbound message here }
   }

22.7. 외부 리소스에서 스크립트 로드

Camel 2.11로 사용 가능

스크립트를 외부화하고 Camel이 "classpath:", "file:" 또는 "http:" 와 같은 리소스에서 로드하도록 할 수 있습니다. 다음 구문을 사용합니다.

"resource:scheme:location"

예를 들어 classpath에서 파일을 참조하려면 다음을 수행합니다.

.setHeader("myHeader").jxpath("resource:classpath:myjxpath.txt")

23장. MVEL

23.1. 개요

MVEL 은 OGNL과 유사하지만 훨씬 더 빠른 것으로 보고되는 Java 기반 동적 언어입니다. MVEL 지원은 camel-mvel 모듈에 있습니다.

23.2. 구문

MVEL dot 구문을 사용하여 Java 메서드를 호출합니다. 예를 들면 다음과 같습니다.

getRequest().getBody().getFamilyName()

MVEL은 동적으로 입력되므로 getFamilyName() 메서드를 호출하기 전에 메시지 본문 인스턴스( 개체 유형)를 캐스팅할 필요가 없습니다. 빈 속성을 호출하는 데 축약 구문을 사용할 수도 있습니다. 예를 들면 다음과 같습니다.

request.body.familyName

23.3. MVEL 모듈 추가

경로에서 MVEL을 사용하려면 예 23.1. “camel-mvel 종속성 추가” 과 같이 프로젝트에 camel-mvel 에 대한 종속성을 추가해야 합니다.

예 23.1. camel-mvel 종속성 추가

<!-- Maven POM File -->
<properties>
  <camel-version>2.23.2.fuse-790054-redhat-00001</camel-version>
  ...
</properties>

<dependencies>
  ...
  <dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-mvel</artifactId>
    <version>${camel-version}</version>
  </dependency>
  ...
</dependencies>

23.4. 기본 제공 변수

표 23.1. “MVEL 변수” MVEL을 사용할 때 액세스할 수 있는 기본 제공 변수를 나열합니다.

표 23.1. MVEL 변수

이름유형설명

org.apache.camel.Exchange

현재 교환

exchange

org.apache.camel.Exchange

현재 교환

예외

Throwable

교환 예외 (있는 경우)

exchangeID

문자열

교환 ID

fault

org.apache.camel.Message

Fault 메시지(있는 경우)

request

org.apache.camel.Message

IN 메시지

응답

org.apache.camel.Message

OUT 메시지

속성

map

교환 속성

property(name)

개체

이름이 지정된 Exchange 속성의 값

property(name, type)

Type

이름이 지정된 Exchange 속성의 형식 값

23.5. 예제

예 23.2. “MVEL을 사용하는 경로” MVEL을 사용하는 경로를 표시합니다.

예 23.2. MVEL을 사용하는 경로

<camelContext>
  <route>
    <from uri="seda:foo"/>
    <filter>
      <language langauge="mvel">request.headers.foo == 'bar'</language>
      <to uri="seda:bar"/>
    </filter>
  </route>
</camelContext>

24장. Object-Graph Navigation Language(OGNL)

24.1. 개요

OGNL은 Java 개체의 속성을 가져오고 설정하기 위한 표현식 언어입니다. 속성 값을 가져오고 설정하는 데 모두 동일한 표현식을 사용합니다. OGNL 지원은 camel-ognl 모듈에 있습니다.

24.2. Camel on EAP 배포

이 구성 요소는 Red Hat JBoss EAP(JBoss Enterprise Application Platform) 컨테이너에 단순화된 배포 모델을 제공하는 EAP의 Camel(Wildfly Camel) 프레임워크에서 지원합니다.

24.3. OGNL 모듈 추가

경로에서 OGNL을 사용하려면 예 24.1. “camel-ognl 종속성 추가” 과 같이 프로젝트에 camel-ognl 에 대한 종속성을 추가해야 합니다.

예 24.1. camel-ognl 종속성 추가

<!-- Maven POM File -->
...
<dependencies>
  ...
  <dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-ognl</artifactId>
    <version>${camel-version}</version>
  </dependency>
  ...
</dependencies>

24.4. 정적 가져오기

애플리케이션 코드에서 ognl() 정적 메서드를 사용하려면 Java 소스 파일에 다음 import 문을 포함합니다.

import static org.apache.camel.language.ognl.OgnlExpression.ognl;

24.5. 기본 제공 변수

표 24.1. “OGNL 변수” OGNL을 사용할 때 액세스할 수 있는 기본 제공 변수를 나열합니다.

표 24.1. OGNL 변수

이름유형설명

org.apache.camel.Exchange

현재 교환

exchange

org.apache.camel.Exchange

현재 교환

예외

Throwable

교환 예외 (있는 경우)

exchangeID

문자열

교환 ID

fault

org.apache.camel.Message

Fault 메시지(있는 경우)

request

org.apache.camel.Message

IN 메시지

응답

org.apache.camel.Message

OUT 메시지

속성

map

교환 속성

property(name)

개체

이름이 지정된 Exchange 속성의 값

property(name, type)

Type

이름이 지정된 Exchange 속성의 형식 값

24.6. 예제

예 24.2. “OGNL을 사용하는 경로” OGNL을 사용하는 경로를 표시합니다.

예 24.2. OGNL을 사용하는 경로

<camelContext>
  <route>
    <from uri="seda:foo"/>
    <filter>
      <language langauge="ognl">request.headers.foo == 'bar'</language>
      <to uri="seda:bar"/>
    </filter>
  </route>
</camelContext>

25장. PHP (더 이상 사용되지 않음)

25.1. 개요

PHP는 웹 개발에 특히 적합한 널리 사용되는 범용 스크립팅 언어입니다. PHP 지원은 camel-script 모듈의 일부입니다.

중요

Apache Camel의 PHP는 더 이상 사용되지 않으며 향후 릴리스에서 제거될 예정입니다.

25.2. script 모듈 추가

경로에서 PHP를 사용하려면 예 25.1. “camel-script 종속성 추가” 에 표시된 대로 camel-script 에 대한 종속성을 프로젝트에 추가해야 합니다.

예 25.1. camel-script 종속성 추가

<!-- Maven POM File -->
...
<dependencies>
  ...
  <dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-script</artifactId>
    <version>${camel-version}</version>
  </dependency>
  ...
</dependencies>

25.3. 정적 가져오기

애플리케이션 코드에서 php() 정적 메서드를 사용하려면 Java 소스 파일에 다음 import 문을 포함합니다.

import static org.apache.camel.builder.script.ScriptBuilder.*;

25.4. 기본 제공 속성

표 25.1. “PHP 속성” PHP를 사용할 때 액세스할 수 있는 기본 제공 속성을 나열합니다.

표 25.1. PHP 속성

속성유형현재의

context

org.apache.camel.CamelContext

Camel 컨텍스트

exchange

org.apache.camel.Exchange

현재 교환

request

org.apache.camel.Message

IN 메시지

응답

org.apache.camel.Message

OUT 메시지

속성

org.apache.camel.builder.script.PropertiesFunction

확인 방법과 함께 작동하여 스크립트 내에서 속성 구성 요소를 더 쉽게 사용할 수 있습니다.

ENGINE_SCOPE 에서 모두 설정된 속성입니다.

25.5. 예제

예 25.2. “PHP를 사용하는 경로” 는 PHP를 사용하는 경로를 표시합니다.

예 25.2. PHP를 사용하는 경로

<camelContext>
  <route>
    <from uri="direct:start"/>
    <choice>
      <when>
        <language language="php">strpos(request.headers.get('user'), 'admin')!== FALSE</language>
        <to uri="seda:adminQueue"/>
      </when>
      <otherwise>
        <to uri="seda:regularQueue"/>
      </otherwise>
    </choice>
  </route>
</camelContext>

25.6. 속성 구성 요소 사용

속성 구성 요소에서 속성 값에 액세스하려면 다음과 같이 기본 제공 속성 속성에서 resolve 메서드를 호출합니다.To access a property value from the properties component, invoke the resolve method on the built-in properties attribute, as follows:

.setHeader("myHeader").php("properties.resolve(PropKey)")

여기서 PropKey 는 확인하려는 속성의 키이며 키 값은 String 유형의 키입니다.

속성 구성 요소에 대한 자세한 내용은 Apache Camel 구성 요소 참조 가이드의 속성을 참조하십시오.https://access.redhat.com/documentation/en-us/red_hat_fuse/7.9/html-single/apache_camel_component_reference/index#properties-component

26장. 자산 교환

26.1. 개요

교환 속성 언어는 교환 속성에 액세스하는 편리한 방법을 제공합니다. 교환 속성 이름 중 하나와 일치하는 키를 제공하는 경우 교환 속성 언어는 해당 값을 반환합니다.

교환 속성 언어는 camel-core 의 일부입니다.

26.2. XML 예

예를 들어 listOfEndpoints 교환 속성에 수신자 목록이 포함된 경우 수신자 목록 패턴을 구현하려면 다음과 같이 경로를 정의할 수 있습니다.

<camelContext>
  <route>
    <from uri="direct:a"/>
    <recipientList>
      <exchangeProperty>listOfEndpoints</exchangeProperty>
    </recipientList>
  </route>
</camelContext>

26.3. Java 예

다음과 같이 Java에서 동일한 수신자 목록 예제를 구현할 수 있습니다.

from("direct:a").recipientList(exchangeProperty("listOfEndpoints"));

27장. Python (DEPRECATED)

27.1. 개요

Python은 다양한 애플리케이션 도메인에 사용되는 매우 강력한 동적 프로그래밍 언어입니다. Python은 종종 Tcl, Perl, Ruby, Scheme 또는 Java와 비교됩니다. Python 지원은 camel-script 모듈의 일부입니다.

중요

Apache Camel의 Python은 더 이상 사용되지 않으며 향후 릴리스에서 제거될 예정입니다.

27.2. script 모듈 추가

경로에서 Python을 사용하려면 예 27.1. “camel-script 종속성 추가” 에 표시된 대로 camel-script 에 대한 종속성을 프로젝트에 추가해야 합니다.

예 27.1. camel-script 종속성 추가

<!-- Maven POM File -->
...
<dependencies>
  ...
  <dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-script</artifactId>
    <version>${camel-version}</version>
  </dependency>
  ...
</dependencies>

27.3. 정적 가져오기

애플리케이션 코드에서 python() 정적 메서드를 사용하려면 Java 소스 파일에 다음 import 문을 포함합니다.

import static org.apache.camel.builder.script.ScriptBuilder.*;

27.4. 기본 제공 속성

표 27.1. “Python 속성” Python을 사용할 때 액세스할 수 있는 기본 제공 속성을 나열합니다.

표 27.1. Python 속성

속성유형현재의

context

org.apache.camel.CamelContext

Camel 컨텍스트

exchange

org.apache.camel.Exchange

현재 교환

request

org.apache.camel.Message

IN 메시지

응답

org.apache.camel.Message

OUT 메시지

속성

org.apache.camel.builder.script.PropertiesFunction

확인 방법과 함께 작동하여 스크립트 내에서 속성 구성 요소를 더 쉽게 사용할 수 있습니다.

ENGINE_SCOPE 에서 모두 설정된 속성입니다.

27.5. 예제

예 27.2. “Python을 사용하는 경로” Python을 사용하는 경로를 표시합니다.

예 27.2. Python을 사용하는 경로

<camelContext>
  <route>
    <from uri="direct:start"/>
    <choice>
      <when>
        <langauge langauge="python">if request.headers.get('user') = 'admin'</langauge>
        <to uri="seda:adminQueue"/>
      </when>
      <otherwise>
        <to uri="seda:regularQueue"/>
      </otherwise>
    </choice>
  </route>
</camelContext>

27.6. 속성 구성 요소 사용

속성 구성 요소에서 속성 값에 액세스하려면 다음과 같이 기본 제공 속성 속성에서 resolve 메서드를 호출합니다.To access a property value from the properties component, invoke the resolve method on the built-in properties attribute, as follows:

.setHeader("myHeader").python("properties.resolve(PropKey)")

여기서 PropKey 는 확인하려는 속성의 키이며 키 값은 String 유형의 키입니다.

속성 구성 요소에 대한 자세한 내용은 Apache Camel 구성 요소 참조 가이드의 속성을 참조하십시오.https://access.redhat.com/documentation/en-us/red_hat_fuse/7.9/html-single/apache_camel_component_reference/index#properties-component

28장. Ref

28.1. 개요

Ref 표현식 언어는 실제로 레지스트리에서 사용자 지정 표현식 을 찾는 방법일 뿐입니다. 이는 특히 XML DSL에서 사용하기에 편리합니다.

Ref 언어는 camel-core 의 일부입니다.

28.2. 정적 가져오기

Java 애플리케이션 코드에서 Ref 언어를 사용하려면 Java 소스 파일에 다음 import 문을 포함합니다.

import static org.apache.camel.language.ref.RefLanguage.ref;

28.3. XML 예

예를 들어 splitter 패턴은 다음과 같이 Ref 언어를 사용하여 사용자 지정 표현식을 참조할 수 있습니다.

<beans ...>
  <bean id="myExpression" class="com.mycompany.MyCustomExpression"/>
  ...
  <camelContext>
    <route>
      <from uri="seda:a"/>
      <split>
        <ref>myExpression</ref>
        <to uri="mock:b"/>
      </split>
    </route>
  </camelContext>
</beans>

28.4. Java 예

이전 경로는 다음과 같이 Java DSL에서도 구현할 수 있습니다.

from("seda:a")
  .split().ref("myExpression")
  .to("seda:b");

29장. Ruby (DEPRECATED)

29.1. 개요

Ruby는 단순성과 생산성에 중점을 두고 동적 오픈 소스 프로그래밍 언어입니다. 읽기 쉽고 쉽게 쓸 수 있는 구문이 있습니다.It has an natural to read and easy to write. Ruby 지원은 camel-script 모듈의 일부입니다.

중요

Apache Camel의 Ruby는 더 이상 사용되지 않으며 향후 릴리스에서 제거될 예정입니다.

29.2. script 모듈 추가

경로에서 Ruby를 사용하려면 예 29.1. “camel-script 종속성 추가” 에 표시된 대로 camel-script 에 대한 종속성을 프로젝트에 추가해야 합니다.

예 29.1. camel-script 종속성 추가

<!-- Maven POM File -->
...
<dependencies>
  ...
  <dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-script</artifactId>
    <version>${camel-version}</version>
  </dependency>
  ...
</dependencies>

29.3. 정적 가져오기

애플리케이션 코드에서 ruby() 정적 메서드를 사용하려면 Java 소스 파일에 다음 import 문을 포함합니다.

import static org.apache.camel.builder.script.ScriptBuilder.*;

29.4. 기본 제공 속성

표 29.1. “Ruby 속성” Ruby를 사용할 때 액세스할 수 있는 기본 제공 속성을 나열합니다.

표 29.1. Ruby 속성

속성유형현재의

context

org.apache.camel.CamelContext

Camel 컨텍스트

exchange

org.apache.camel.Exchange

현재 교환

request

org.apache.camel.Message

IN 메시지

응답

org.apache.camel.Message

OUT 메시지

속성

org.apache.camel.builder.script.PropertiesFunction

확인 방법과 함께 작동하여 스크립트 내에서 속성 구성 요소를 더 쉽게 사용할 수 있습니다.

ENGINE_SCOPE 에서 모두 설정된 속성입니다.

29.5. 예제

예 29.2. “Ruby를 사용하는 경로” 은 Ruby를 사용하는 경로를 표시합니다.

예 29.2. Ruby를 사용하는 경로

<camelContext>
  <route>
    <from uri="direct:start"/>
    <choice>
      <when>
        <langauge langauge="ruby">$request.headers['user'] == 'admin'</langauge>
        <to uri="seda:adminQueue"/>
      </when>
      <otherwise>
        <to uri="seda:regularQueue"/>
      </otherwise>
    </choice>
  </route>
</camelContext>

29.6. 속성 구성 요소 사용

속성 구성 요소에서 속성 값에 액세스하려면 다음과 같이 기본 제공 속성 속성에서 resolve 메서드를 호출합니다.To access a property value from the properties component, invoke the resolve method on the built-in properties attribute, as follows:

.setHeader("myHeader").ruby("properties.resolve(PropKey)")

여기서 PropKey 는 확인하려는 속성의 키이며 키 값은 String 유형의 키입니다.

속성 구성 요소에 대한 자세한 내용은 Apache Camel 구성 요소 참조 가이드의 속성을 참조하십시오.https://access.redhat.com/documentation/en-us/red_hat_fuse/7.9/html-single/apache_camel_component_reference/index#properties-component

30장. 간단한 언어

초록

간단한 언어는 특히 교환 오브젝트의 다양한 부분에 액세스하고 조작하기 위해 Apache Camel에서 개발한 언어입니다. 이 언어는 원래 생성되었을 때만큼 간단하지 않으며 이제 포괄적인 논리 연산자 및 조합 세트가 있습니다.

30.1. Java DSL

30.1.1. Java DSL의 간단한 표현식

Java DSL에는 경로에서 simple() 명령을 사용하기 위한 두 가지 스타일이 있습니다. 다음과 같이 simple() 명령을 프로세서에 인수로 전달할 수 있습니다.

from("seda:order")
  .filter(simple("${in.header.foo}"))
  .to("mock:fooOrders");

또는 processor에서 sub-clause로 simple() 명령을 호출할 수 있습니다. 예를 들면 다음과 같습니다.

from("seda:order")
  .filter()
  .simple("${in.header.foo}")
  .to("mock:fooOrders");

30.1.2. 문자열에 포함

일반 텍스트 문자열 내에 간단한 표현식을 포함하는 경우 자리 표시자 구문 ${Expression} 을 사용해야 합니다. 예를 들어 in.header.name 표현식을 문자열에 포함하려면 다음을 수행합니다.

simple("Hello ${in.header.name}, how are you?")

30.1.3. 시작 및 종료 토큰 사용자 정의

Java에서 change function StartToken 정적 메서드를 호출하고 SimpleLanguage 오브젝트에서 changeFunctionEndToken 정적 메서드를 호출하여 시작 및 종료 토큰({} )을 사용자 지정할 수 있습니다.

예를 들어 다음과 같이 시작 및 종료 토큰을 Java의 [] 로 변경할 수 있습니다.

// Java
import org.apache.camel.language.simple.SimpleLanguage;
...
SimpleLanguage.changeFunctionStartToken("[");
SimpleLanguage.changeFunctionEndToken("]");
참고

시작 및 종료 토큰을 사용자 정의하면 클래스 경로에서 동일한 camel-core 라이브러리를 공유하는 모든 Apache Camel 애플리케이션에 영향을 미칩니다. 예를 들어 OSGi 서버에서는 많은 애플리케이션에 영향을 미칠 수 있지만 웹 애플리케이션(WAR 파일)에서는 웹 애플리케이션 자체에만 영향을 미칩니다.

30.2. XML DSL

30.2.1. XML DSL의 간단한 표현식

XML DSL에서는 표현식을 간단한 요소 내에 배치하여 간단한 표현식을 사용할 수 있습니다. 예를 들어 foo 헤더의 내용을 기반으로 필터링을 수행하는 경로를 정의하려면 다음을 수행합니다.

<route id="simpleExample">
  <from uri="seda:orders"/>
  <filter>
    <simple>${in.header.foo}</simple>
    <to uri="mock:fooOrders"/>
  </filter>
</route>

30.2.2. 대체 자리 표시자 구문

예를 들어 Spring 속성 자리 표시자 또는 OSGi 블루프린트 속성 자리 표시자가 있는 경우, ${Expression} 구문이 다른 속성 자리 표시자 구문과 충돌하는 경우가 있습니다. 이 경우 단순 표현식에 대해 대체 구문 $simple{Expression} 을 사용하여 자리 표시자를 모호할 수 있습니다. 예를 들면 다음과 같습니다.

<simple>Hello $simple{in.header.name}, how are you?</simple>

30.2.3. 시작 및 종료 토큰 사용자 정의

XML 구성에서 SimpleLanguage 인스턴스를 재정의하여 시작 및 종료 토큰(기본적으로{} )을 사용자 지정할 수 있습니다. 예를 들어 시작 및 끝 토큰을 [] 로 변경하려면 다음과 같이 XML 구성 파일에 새 SimpleLanguage 8080을 정의합니다.

<bean id="simple" class="org.apache.camel.language.simple.SimpleLanguage">
  <constructor-arg name="functionStartToken" value="["/>
  <constructor-arg name="functionEndToken" value="]"/>
</bean>
참고

시작 및 종료 토큰을 사용자 정의하면 클래스 경로에서 동일한 camel-core 라이브러리를 공유하는 모든 Apache Camel 애플리케이션에 영향을 미칩니다. 예를 들어 OSGi 서버에서는 많은 애플리케이션에 영향을 미칠 수 있지만 웹 애플리케이션(WAR 파일)에서는 웹 애플리케이션 자체에만 영향을 미칩니다.

30.2.4. XML DSL의 공백 및 자동 할당

기본적으로 간단한 표현식을 따르는 공백은 XML DSL에서 자동으로 트리밍됩니다. 공백을 중심으로 하는 이 표현식은 다음과 같습니다.

<transform>
  <simple>
    data=${body}
  </simple>
</transform>

이 표현식은 자동으로 트리밍되므로 이 표현식(백백 공간 주변 없음)과 동일합니다.

<transform>
  <simple>data=${body}</simple>
</transform>

식 전이나 후에 줄 바꿈 문자를 포함하려는 경우 다음과 같이 줄 바꿈 문자를 명시적으로 추가할 수 있습니다.

<transform>
  <simple>data=${body}\n</simple>
</transform>

또는 트리밍 속성을 false 로 설정하여 다음과 같이 자동 분석을 전환할 수 있습니다.

<transform trim="false">
  <simple>data=${body}
</simple>
</transform>

30.3. 외부 스크립트 호출

30.3.1. 개요

여기에 설명된 대로 외부 리소스에 저장된 간단한 스크립트를 실행할 수 있습니다.

30.3.2. 스크립트 리소스의 구문

다음 구문을 사용하여 외부 리소스로 저장된 Simple 스크립트에 액세스합니다.

resource:Scheme:Location

여기서 Scheme: classpath:, file: 또는 http: 중 하나일 수 있습니다.

예를 들어 classpath에서 mysimple.txt 스크립트를 읽으려면

simple("resource:classpath:mysimple.txt")

30.4. 표현식

30.4.1. 개요

간단한 언어는 메시지 교환의 다른 부분을 반환하는 다양한 기본 표현식을 제공합니다. 예를 들어 simple("$header.timeOfDay}") 표현식은 수신 메시지에서 timeOfDay 라는 헤더의 내용을 반환합니다.

참고

Apache Camel 2.9부터 변수 값을 반환하려면 항상 자리 표시자 구문 ${Expression} 을 사용해야 합니다. enclosing 토큰(${})을 생략하는 것은 허용되지 않습니다.

30.4.2. 단일 변수의 콘텐츠

간단한 언어를 사용하여 제공된 변수에 따라 문자열 표현식을 정의할 수 있습니다. 예를 들어 양식의 변수를 사용하여 다음과 같이 HeaderName 헤더의 값을 가져올 수 있습니다.

simple("${in.header.foo}")

30.4.3. 문자열에 포함된 변수

예를 들어, string expression 전환에 간단한 변수를 포함할 수 있습니다.

simple("Received a message from ${in.header.user} on ${date:in.header.date:yyyyMMdd}.")

30.4.4. 날짜 및 Cryostat 변수

교환의 모든 부분에 액세스하는 변수( 표 30.1. “간단한 언어의 변수”참조)를 제공하는 것뿐만 아니라 간단한 언어에서는 형식 지정 날짜, date:pattern, meaning() 메서드 호출에 대한 특수 변수도 제공합니다. 예를 들어 다음과 같이 date 및 metrics 변수를 사용할 수 있습니다.

simple("Todays date is ${date:now:yyyyMMdd}")
simple("The order type is ${bean:orderService?method=getOrderType}")

30.4.5. 결과 유형 지정

표현식의 결과 유형을 명시적으로 지정할 수 있습니다. 이는 주로 결과 유형을 부울 또는 숫자 유형으로 변환하는 데 유용합니다.

Java DSL에서 결과 유형을 simple() 에 대한 추가 인수로 지정합니다. 예를 들어 정수 결과를 반환하려면 다음과 같이 간단한 표현식을 평가할 수 있습니다.

...
.setHeader("five", simple("5", Integer.class))

XML DSL에서 resultType 특성을 사용하여 결과 유형을 지정합니다. 예를 들면 다음과 같습니다.

<setHeader headerName="five">
  <!-- use resultType to indicate that the type should be a java.lang.Integer -->
  <simple resultType="java.lang.Integer">5</simple>
</setHeader>

30.4.6. 동적 헤더 키

Camel 2.17에서 setHeadersetExchange 속성을 사용하면 키 이름이 단순 언어 표현식인 경우 Simple 언어를 사용하여 동적 헤더 키를 사용할 수 있습니다.

<camelContext xmlns="http://camel.apache.org/schema/spring">
  <route>
    <from uri="direct:start"/>
      <setHeader headerName="$simple{type:org.apache.camel.spring.processor.SpringSetPropertyNameDynamicTest$TestConstans.EXCHANGE_PROP_TX_FAILED}">
        <simple>${type:java.lang.Boolean.TRUE}</simple>
      </setHeader>
    <to uri="mock:end"/>
  </route>
</camelContext>

30.4.7. 중첩된 표현식

단순 표현식은 nested Cryostat- Cryostat일 수 있습니다. 예를 들면 다음과 같습니다.

simple("${header.${bean:headerChooser?method=whichHeader}}")

30.4.8. 상수 또는 열거 액세스

다음 구문을 사용하여 Quarkus의 상수 또는 enum 필드에 액세스할 수 있습니다.

type:ClassName.Field

예를 들어 다음 Java enum 유형을 고려하십시오.

package org.apache.camel.processor;
...
public enum Customer {
    GOLD, SILVER, BRONZE
}

다음과 같이 Customer enum 필드에 액세스할 수 있습니다.

 from("direct:start")
    .choice()
        .when().simple("${header.customer} ==
          ${type:org.apache.camel.processor.Customer.GOLD}")
            .to("mock:gold")
        .when().simple("${header.customer} ==
          ${type:org.apache.camel.processor.Customer.SILVER}")
            .to("mock:silver")
        .otherwise()
            .to("mock:other");

30.4.9. OGNL 표현식

OGNL(오브젝트 그래프 탐색 언어)은 chain-like fashion으로 빈 메서드를 호출하기 위한 표기법입니다. 메시지 본문에 Java 8080이 포함된 경우 OGNL 표기법을 사용하여 빈 속성에 쉽게 액세스할 수 있습니다. 예를 들어 메시지 본문이 getAddress() 접근자가 있는 Java 개체인 경우 Address 개체 및 Address 오브젝트의 속성에 다음과 같이 액세스할 수 있습니다.

simple("${body.address}")
simple("${body.address.street}")
simple("${body.address.zip}")
simple("${body.address.city}")

여기서 표기법 ${body.address.street}${body.getAddress.getStreet}.의 약어입니다.

30.4.10. OGNL null-safe operator

null 안전 연산자( ? )를 사용하여 본문에 주소가 없는 경우 null 포인터 예외가 발생하지 않도록 할 수 있습니다. 예를 들면 다음과 같습니다.

simple("${body?.address?.street}")

본문이 java.util.Map 유형인 경우 다음 표기법을 사용하여 맵에서 키 foo 를 사용하여 값을 조회할 수 있습니다.

simple("${body[foo]?.name}")

30.4.11. OGNL 목록 요소 액세스

또한 대괄호 표기법을 사용하여 목록의 요소에 액세스할 수도 있습니다. 예를 들면 다음과 같습니다.

simple("${body.address.lines[0]}")
simple("${body.address.lines[1]}")
simple("${body.address.lines[2]}")

last 키워드는 목록의 마지막 요소의 인덱스를 반환합니다. 예를 들어 다음과 같이 목록의 두 번째 마지막 요소에 액세스할 수 있습니다.

simple("${body.address.lines[last-1]}")

size 방법을 사용하여 다음과 같이 목록 크기를 쿼리할 수 있습니다.

simple("${body.address.lines.size}")

30.4.12. OGNL 배열 길이 액세스

다음과 같이 길이 방법을 통해 Java 배열의 길이에 액세스할 수 있습니다.

String[] lines = new String[]{"foo", "bar", "cat"};
exchange.getIn().setBody(lines);

simple("There are ${body.length} lines")

30.5. 서술자

30.5.1. 개요

같음에 대한 식을 테스트하여 서술자를 구성할 수 있습니다. 예를 들어, 조건자 simple("$header.timeOfDay} == '14:30'"), 들어오는 메시지의 timeOfDay 헤더가 14:30 인지 여부를 테스트합니다.

또한 resultType 을 부울로 지정할 때마다 표현식은 표현식 대신 서술자로 평가됩니다. 이렇게 하면 이러한 표현식에 서술자 구문을 사용할 수 있습니다.

30.5.2. 구문

간단한 서술자를 사용하여 교환(headers, 메시지 본문 등)의 다양한 부분을 테스트할 수도 있습니다. 간단한 서술자에는 다음과 같은 일반 구문이 있습니다.

${LHSVariable} Op RHSValue

여기서 LHSVariable 은 왼쪽의 변수인 LHSVariable표 30.1. “간단한 언어의 변수” 에 표시된 변수 중 하나이고 오른쪽의 RHSValue 값은 다음 중 하나입니다.

  • 다른 변수 ${RHSVariable}.
  • 작은따옴표로 묶은 문자열 리터럴 '.
  • 작은따옴표로 묶은 숫자 상수 '.
  • null 개체, null.

단순 언어는 항상 RHS 값을 LHS 값의 유형으로 변환하려고 합니다.

참고

간단한 언어는 RHS를 변환하려고 하지만 Operator에 따라 LHS를 비교하기 전에 적절한 Type으로 캐스팅해야 할 수 있습니다.

30.5.3. 예

예를 들어 다음과 같이 간단한 문자열 비교 및 숫자 비교를 수행할 수 있습니다.

simple("${in.header.user} == 'john'")

simple("${in.header.number} > '100'")  // String literal can be converted to integer

다음과 같이 왼쪽이 쉼표로 구분된 목록의 멤버인지 테스트할 수 있습니다.

simple("${in.header.type} in 'gold,silver'")

왼쪽이 다음과 같이 정규식과 일치하는지 테스트할 수 있습니다.

simple("${in.header.number} regex '\d{4}'")

다음과 같이 is 연산자를 사용하여 왼쪽의 유형을 테스트할 수 있습니다.

simple("${in.header.type} is 'java.lang.String'")
simple("${in.header.type} is 'String'") // You can abbreviate java.lang. types

다음과 같이 왼쪽이 지정된 숫자 범위(범위가 포함됨)에 있는지 여부를 테스트할 수 있습니다.

simple("${in.header.number} range '100..199'")

30.5.4. 연결

논리 결합, && amp; 및 || 를 사용하여 서술자를 결합할 수도 있습니다.

예를 들어, 다음은 &amp ;& amp; 조합(논리적 및)을 사용하는 표현식입니다.

simple("${in.header.title} contains 'Camel' && ${in.header.type} == 'gold'")

그리고 여기에 || 를 사용하는 표현식(논리적 포함 또는)이 있습니다.

simple("${in.header.title} contains 'Camel' || ${in.header.type} == 'gold'")

30.6. 변수 참조

30.6.1. 변수 테이블

표 30.1. “간단한 언어의 변수” 간단한 언어에서 지원하는 모든 변수를 표시합니다.

표 30.1. 간단한 언어의 변수

Variable유형설명

camelContext

개체

Camel 컨텍스트입니다. OGNL 표현식을 지원합니다.

camelId

문자열

Camel 컨텍스트의 ID 값입니다.

exchangeId

문자열

교환의 ID 값입니다.

id

문자열

메시지 ID 값입니다.

body

개체

메시지 본문 입니다. OGNL 표현식을 지원합니다.

in.body

개체

메시지 본문 입니다. OGNL 표현식을 지원합니다.

out.body

개체

외부 메시지 본문입니다.

bodyAs(Type)

유형

In 메시지 본문으로, 지정된 유형으로 변환됩니다. 모든 유형, 유형 에서는 byte[], string,IntegerLong 형식을 제외하고 정규화된 Java 이름을 사용하여 지정해야 합니다. 변환된 본문은 null일 수 있습니다.

mandatoryBodyAs(Type)

유형

In 메시지 본문으로, 지정된 유형으로 변환됩니다. 모든 유형, 유형 에서는 byte[], string,IntegerLong 형식을 제외하고 정규화된 Java 이름을 사용하여 지정해야 합니다. 변환된 본문은 null이 아닌 것으로 예상됩니다.

header.HeaderName

개체

In 메시지의 HeaderName 헤더입니다. OGNL 표현식을 지원합니다.

header[HeaderName]

개체

In message의 HeaderName 헤더(alternative 구문)입니다.

headers.HeaderName

개체

In 메시지의 HeaderName 헤더입니다.

headers[HeaderName]

개체

In message의 HeaderName 헤더(alternative 구문)입니다.

in.header.HeaderName

개체

In 메시지의 HeaderName 헤더입니다. OGNL 표현식을 지원합니다.

in.header[HeaderName]

개체

In message의 HeaderName 헤더(alternative 구문)입니다.

in.headers.HeaderName

개체

In 메시지의 HeaderName 헤더입니다. OGNL 표현식을 지원합니다.

in.headers[HeaderName]

개체

In message의 HeaderName 헤더(alternative 구문)입니다.

out.header.HeaderName

개체

Out 메시지의 HeaderName 헤더입니다.

out.header[HeaderName]

개체

Out 메시지의 HeaderName 헤더(alternative 구문)입니다.

out.headers.HeaderName

개체

Out 메시지의 HeaderName 헤더입니다.

out.headers[HeaderName]

개체

Out 메시지의 HeaderName 헤더(alternative 구문)입니다.

headerAs(Key,Type)

유형

지정된 유형으로 변환되는 헤더입니다. 모든 유형, 유형 에서는 byte[], string,IntegerLong 형식을 제외하고 정규화된 Java 이름을 사용하여 지정해야 합니다. 변환된 값은 null일 수 있습니다.

headers

map

모든 In 헤더( java.util.Map 유형)입니다.

in.headers

map

모든 In 헤더( java.util.Map 유형)입니다.

exchangeProperty.PropertyName

개체

교환의 PropertyName 속성입니다.

exchangeProperty[PropertyName]

개체

교환의 PropertyName 속성(ternative 구문).

exchangeProperty.PropertyName.OGNL

개체

교환의 PropertyName 속성 및 Camel OGNL 표현식을 사용하여 해당 값을 호출합니다.

sys.SysPropertyName

문자열

SysPropertyName Java 시스템 속성입니다.

sysenv.SysEnvVar

문자열

SysEnvVar 시스템 환경 변수.

예외

문자열

Exchange.getException() 의 예외 개체 또는 이 값이 null인 경우 Exchange.EXCEPTION_CAUGHT 속성에서 catch된 예외, 그렇지 않으면 null입니다. OGNL 표현식을 지원합니다.

exception.message

문자열

교환에 예외가 설정된 경우 Exception.getMessage() 값을 반환합니다. 그렇지 않으면 null 을 반환합니다.

exception.stacktrace

문자열

교환에 예외가 설정된 경우 Exception.getStackTrace() 값을 반환합니다. 그렇지 않으면 null 을 반환합니다. 참고: 간단한 언어는 먼저 Exchange.getException() 에서 예외를 검색하려고 합니다. 해당 속성을 설정하지 않으면 Exchange.getProperty(Exchange.CAUGHT_EXCEPTION) 를 호출하여 catch된 예외를 확인합니다.

date:command:pattern

문자열

java.text.SimpleDateFormat 패턴을 사용하여 포맷된 날짜입니다. 다음 명령이 지원됩니다. 이제 현재 날짜 및 시간, header. HeaderName 또는 in.header.headerName은 In 메시지의HeaderName 헤더에 java.util.Date 오브젝트를 사용합니다 . out.headerName은 Out 메시지의HeaderName 헤더에 있는 java.util.Date 오브젝트를 사용합니다.

Cryostat:CryostatID.Method

개체

참조된 8080에서 메서드를 호출하고 메서드 호출의 결과를 반환합니다. 메서드 이름을 지정하려면 pinID .Method구문을 사용하거나 blankID ?method=method Name구문을 사용할 수 있습니다.

ref:CryostatID

개체

레지스트리에서 ID, 8080ID를 사용하여 8080을 조회하고, 8080 자체에 대한 참조를 반환합니다. 예를 들어 splitter EIP를 사용하는 경우 이 변수를 사용하여 분할 알고리즘을 구현하는 빈을 참조할 수 있습니다.

속성:

문자열

Key 속성 자리 표시자의 값입니다.

속성:위치:

문자열

속성 파일의 위치는 위치에 따라 제공되는 Key 속성 자리 표시자의 값입니다.

threadName

문자열

현재 스레드의 이름입니다.

routeId

문자열

Exchange 가 라우팅되는 현재 경로의 ID를 반환합니다.

유형:이름[.Field]

개체

FQN(Fully-Qualified-Name)을 통해 유형 또는 필드를 참조합니다. 필드를 참조하려면 .field를 추가합니다. 예를 들어 Exchange 클래스의 FILE_NAME 상수 필드를 type:org.apache.camel.Exchange.FILE_NAME으로 참조할 수 있습니다.

collate(group)

list

Camel 2.17에서 병합 함수는 메시지 본문을 반복하고 데이터를 특정 크기의 하위 목록으로 그룹화합니다. Splitter EIP와 함께 사용하여 메시지 본문 및 그룹을 분할하거나 하위 메시지를 N 하위 목록 그룹으로 일괄 처리할 수 있습니다.

skip(number)

Cryostat

skip 함수는 메시지 본문을 반복하고 첫 번째 항목 수를 건너뜁니다. Splitter EIP와 함께 사용하여 메시지 본문을 분할하고 첫 번째 N 개의 항목을 건너뛸 수 있습니다.

30.7. Operator 참조

30.7.1. 바이너리 Operator

간단한 언어 서술자의 바이너리 Operator는 표 30.2. “간단한 언어를 위한 바이너리 Operator” 에 표시됩니다.

표 30.2. 간단한 언어를 위한 바이너리 Operator

Operator설명

==

동일.

=~

케이스 무시와 동일합니다. 문자열 값을 비교할 때 대소문자를 무시합니다.

>

보다 큼.

>=

크거나 같음.

<

보다 적습니다.

작거나 같음.

!=

같지 않음.

포함

LHS 문자열에 RHS 문자열이 포함되어 있는지 테스트합니다.

포함되지 않음

LHS 문자열에 RHS 문자열이 포함되어 있지 않은지 테스트합니다.

regex

LHS 문자열이 RHS 정규식과 일치하는지 테스트합니다.

not regex

LHS 문자열이 RHS 정규식과 일치하지 않는지 테스트합니다.

in

LHS 문자열이 RHS 쉼표로 구분된 목록에 표시되는지 테스트합니다.

해당 없음

LHS 문자열이 RHS 쉼표로 구분된 목록에 나타나지 않는지 테스트합니다.

is

LHS가 RHS Java 유형의 인스턴스인지 테스트합니다(Java instanceof operator 사용).

해당 없음

LHS가 RHS Java 유형의 인스턴스가 아닌지 테스트합니다(Java instanceof operator 사용).

범위

LHS 번호가 RHS 범위에 있는지 테스트합니다(범위의 형식은 'min…​max').

범위가 아님

LHS 번호가 RHS 범위에 있지 않은지 테스트합니다(범위의 형식은 'min…​max').

다음으로 시작

Camel 2.18의 새로운 기능. LHS 문자열이 RHS 문자열로 시작하는지 테스트합니다.

다음으로 종료

Camel 2.18의 새로운 기능. LHS 문자열이 RHS 문자열로 종료되는지 테스트합니다.

30.7.2. 단항 연산자 및 문자 이스케이프

간단한 언어 서술자의 바이너리 Operator는 표 30.3. “간단한 언어에 대한 단항 Operator” 에 표시됩니다.

표 30.3. 간단한 언어에 대한 단항 Operator

Operator설명

++

숫자를 1씩 늘립니다.

--

숫자를 1로 줄입니다.

\n

줄 바꿈 문자입니다.

\r

반환 문자입니다.

\t

탭 문자입니다.

\

(obsolete) Camel 버전 2.11부터 백슬래시 이스케이프 문자는 지원되지 않습니다.

30.7.3. 서술자 결합

표 30.4. “Simple Language Predicates의 결합” 에 표시된 결합을 사용하여 두 개 이상의 간단한 언어 서술자를 결합할 수 있습니다.

표 30.4. Simple Language Predicates의 결합

Operator설명

&&

두 서술자를 논리 및 와 결합합니다.

||

논리 포함 또는 두 서술자를 결합합니다.

더 이상 사용되지 않음 대신 &amp ;& amp;를 사용하십시오.

또는

더 이상 사용되지 않음 대신 || 를 사용하십시오.

31장. SpEL

31.1. 개요

Spring Expression Language (SpEL) 는 Spring 3과 함께 제공되는 오브젝트 그래프 탐색 언어이며, 경로에 서술자 및 표현식을 구성하는 데 사용할 수 있습니다. SpEL의 주목할 만한 기능은 레지스트리에서 빈에 쉽게 액세스할 수 있는 기능입니다.

31.2. 구문

SpEL 표현식은 일반 텍스트 문자열에 포함될 수 있도록 자리 표시자 구문 #{SpelExpression} 을 사용해야 합니다(즉, SpEL에는 표현식 템플릿 표시가 활성화되어 있습니다).

SPEL은 @ CryostatID 구문을 사용하여 레지스트리에서 빈 을 검색할 수도 있습니다(일반적으로 Spring 레지스트리). 예를 들어 ID, headerUtils, 메서드, count() (현재 메시지의 헤더 수를 계산하는) count()가 있는 8080이 있는 경우 다음과 같이 SpEL 서술자에서 headerUtils Cryostat를 사용할 수 있습니다.

#{@headerUtils.count > 4}

31.3. SpEL 패키지 추가

경로에서 SpEL을 사용하려면 예 31.1. “camel-spring 종속성 추가” 과 같이 카멜 자에 대한 종속성 을 프로젝트에 추가해야 합니다.

예 31.1. camel-spring 종속성 추가

<!-- Maven POM File -->
<properties>
  <camel-version>2.23.2.fuse-790054-redhat-00001</camel-version>
  ...
</properties>

<dependencies>
  ...
  <dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-spring</artifactId>
    <version>${camel-version}</version>
  </dependency>
  ...
</dependencies>

31.4. 변수

표 31.1. “SPEL 변수” SpEL을 사용할 때 액세스할 수 있는 변수를 나열합니다.

표 31.1. SPEL 변수

Variable유형설명

교환

현재 교환은 루트 오브젝트입니다.

exchange

교환

현재 교환입니다.

exchangeId

문자열

현재 교환의 ID입니다.

예외

Throwable

교환 예외(있는 경우)입니다.

fault

메시지

오류 메시지(있는 경우).

request

메시지

교환의 메시지입니다.

응답

메시지

교환의 아웃 메시지(있는 경우)입니다.

속성

map

교환 속성입니다.

속성(이름)

개체

이름으로 키가 지정된 교환 속성입니다.

속성(이름,유형)

유형

이름으로 키 지정된 교환 속성의 유형으로 변환됩니다. Type.

31.5. XML 예

예를 들어, 헤더의 값이 USA 메시지만 선택하려면 다음 SpEL 표현식을 사용할 수 있습니다.

<route>
  <from uri="SourceURL"/>
  <filter>
    <spel>#{request.headers['Country'] == 'USA'}}</spel>
    <to uri="TargetURL"/>
  </filter>
</route>

31.6. Java 예

다음과 같이 Java DSL에서 동일한 경로를 정의할 수 있습니다.

from("SourceURL")
  .filter().spel("#{request.headers['Country'] == 'USA'}")
  .to("TargetURL");

다음 예제에서는 일반 텍스트 문자열에 SpEL 표현식을 포함하는 방법을 보여줍니다.

from("SourceURL")
  .setBody(spel("Hello #{request.body}! What a beautiful #{request.headers['dayOrNight']}"))
  .to("TargetURL");

32장. Cryostat 언어

초록

XML 메시지를 처리할 때 Cryostat 언어를 사용하면 메시지의 Document Object Model(DOM)에서 작동하는 Cryostat 표현식을 지정하여 메시지의 일부를 선택할 수 있습니다. Cryostat 서술자를 정의하여 요소 또는 속성의 내용을 테스트할 수도 있습니다.

32.1. Java DSL

32.1.1. 기본 표현식

xpath("Expression ")을 사용하여 현재 교환에 대해 Cryostat 표현식을 평가할 수 있습니다(여기서 the Cryostat 표현식은 현재 In 메시지의 본문에 적용됨). xpath() 표현식의 결과는 XML 노드(또는 둘 이상의 노드가 일치하는 경우 노드 세트)입니다.

예를 들어 현재 In 메시지 본문에서 /person/name 요소의 내용을 추출하고 이를 사용하여 user 라는 헤더를 설정하려면 다음과 같은 경로를 정의할 수 있습니다.

from("queue:foo")
    .setHeader("user", xpath("/person/name/text()"))
    .to("direct:tie");

xpath()setHeader() 에 대한 인수로 지정하는 대신 fluent builder xpath() 명령 Cryostat- case를 사용할 수 있습니다.

from("queue:foo")
    .setHeader("user").xpath("/person/name/text()")
    .to("direct:tie");

결과를 특정 유형으로 변환하려면 xpath() 의 두 번째 인수로 결과 유형을 지정합니다. 예를 들어 결과 유형이 문자열 임을 명시적으로 지정하려면 다음을 수행합니다.

xpath("/person/name/text()", String.class)

32.1.2. 네임스페이스

일반적으로 XML 요소는 네임스페이스 URI로 식별되는 스키마에 속합니다. 이와 같은 문서를 처리할 때 Cryostat 표현식에서 요소 이름을 명확하게 식별할 수 있도록 네임스페이스 URI를 접두사와 연결해야 합니다. Apache Camel은 네임스페이스와 접두사 간 연결을 정의할 수 있는 Helper 클래스 org.apache.camel.builder.xml.Namespaces 를 제공합니다.

예를 들어 접두사 cust 를 네임스페이스, http://acme.com/customer/record 와 연결한 다음 요소 /cust:person/cust:name 의 내용을 추출하려면 다음과 같은 경로를 정의할 수 있습니다.

import org.apache.camel.builder.xml.Namespaces;
...
Namespaces ns = new Namespaces("cust", "http://acme.com/customer/record");

from("queue:foo")
    .setHeader("user", xpath("/cust:person/cust:name/text()", ns))
    .to("direct:tie");

Namespaces 오브젝트 ns 를 추가 인수로 전달하여 xpath() 표현식 빌더에서 네임스페이스 정의를 사용할 수 있도록 하는 위치. 여러 네임스페이스를 정의해야 하는 경우 다음과 같이 Namespace.add() 메서드를 사용합니다.

import org.apache.camel.builder.xml.Namespaces;
...
Namespaces ns = new Namespaces("cust", "http://acme.com/customer/record");
ns.add("inv", "http://acme.com/invoice");
ns.add("xsi", "http://www.w3.org/2001/XMLSchema-instance");

결과 유형을 지정하고 네임스페이스를 정의해야 하는 경우 다음과 같이 3 단계의 xpath() 형식을 사용할 수 있습니다.

xpath("/person/name/text()", String.class, ns)

32.1.3. 네임스페이스 감사

Cryostat 표현식을 사용할 때 발생할 수 있는 가장 빈번한 문제 중 하나는 들어오는 메시지에 나타나는 네임스페이스와 Cryostat 표현식에 사용되는 네임스페이스 간에 불일치가 있다는 것입니다. 이러한 종류의 문제를 해결하기 위해 Cryostat 언어는 들어오는 모든 메시지의 모든 네임스페이스를 시스템 로그로 덤프하는 옵션을 지원합니다.

INFO 로그 수준에서 네임스페이스 로깅을 활성화하려면 다음과 같이 Java DSL에서 logNamespaces 옵션을 활성화합니다.

xpath("/foo:person/@id", String.class).logNamespaces()

또는 org.apache.camel.builder.xml.XPathBuilder 로거에서 TRACE 수준 로깅을 활성화하도록 로깅 시스템을 구성할 수 있습니다.

네임스페이스 로깅이 활성화되면 처리된 각 메시지에 대해 다음과 같은 로그 메시지가 표시됩니다.

2012-01-16 13:23:45,878 [stSaxonWithFlag] INFO  XPathBuilder  -
Namespaces discovered in message: {xmlns:a=[http://apache.org/camel],
DEFAULT=[http://apache.org/default],
xmlns:b=[http://apache.org/camelA, http://apache.org/camelB]}

32.2. XML DSL

32.2.1. 기본 표현식

XML DSL에서 Cryostat 표현식을 평가하려면 xpath 요소 내에 Cryostat 표현식을 배치합니다. Cryostat 표현식은 현재 In 메시지의 본문에 적용되고 XML 노드(또는 노드 세트)를 반환합니다. 일반적으로 반환된 XML 노드는 자동으로 문자열로 변환됩니다.

예를 들어 현재 In 메시지 본문에서 /person/name 요소의 내용을 추출하고 이를 사용하여 user 라는 헤더를 설정하려면 다음과 같은 경로를 정의할 수 있습니다.

<beans ...>

  <camelContext xmlns="http://camel.apache.org/schema/spring">
    <route>
      <from uri="queue:foo"/>
      <setHeader headerName="user">
        <xpath>/person/name/text()</xpath>
      </setHeader>
      <to uri="direct:tie"/>
    </route>
  </camelContext>

</beans>

결과를 특정 유형으로 변환하려면 resultType 특성을 Java 유형 이름으로 설정하여 결과 유형을 지정합니다(정규화된 형식 이름을 지정해야 함). 예를 들어 결과 유형이 java.lang.String 임을 명시적으로 지정하려면(여기서 java.lang. 접두사를 생략할 수 있습니다).

<xpath resultType="String">/person/name/text()</xpath>

32.2.2. 네임스페이스

요소가 하나 이상의 XML 스키마에 속하는 문서를 처리하는 경우 일반적으로 namespace URI를 접두사와 연결해야 합니다. 따라서 Cryostat 표현식에서 요소 이름을 모호하게 식별할 수 있습니다. 접두사를 네임스페이스 URI와 연결하는 데 표준 XML 메커니즘을 사용할 수 있습니다. 즉, 다음과 같은 속성을 설정할 수 있습니다. xmlns:Prefix="NamespaceURI".

예를 들어 접두사 cust 를 네임스페이스, http://acme.com/customer/record 와 연결한 다음 요소 /cust:person/cust:name 의 내용을 추출하려면 다음과 같은 경로를 정의할 수 있습니다.

<beans ...>

  <camelContext xmlns="http://camel.apache.org/schema/spring"
                xmlns:cust="http://acme.com/customer/record" >
    <route>
      <from uri="queue:foo"/>
      <setHeader headerName="user">
        <xpath>/cust:person/cust:name/text()</xpath>
      </setHeader>
      <to uri="direct:tie"/>
    </route>
  </camelContext>

</beans>

32.2.3. 네임스페이스 감사

Cryostat 표현식을 사용할 때 발생할 수 있는 가장 빈번한 문제 중 하나는 들어오는 메시지에 나타나는 네임스페이스와 Cryostat 표현식에 사용되는 네임스페이스 간에 불일치가 있다는 것입니다. 이러한 종류의 문제를 해결하기 위해 Cryostat 언어는 들어오는 모든 메시지의 모든 네임스페이스를 시스템 로그로 덤프하는 옵션을 지원합니다.

INFO 로그 수준에서 네임스페이스 로깅을 활성화하려면 다음과 같이 XML DSL에서 logNamespaces 옵션을 활성화합니다.

<xpath logNamespaces="true" resultType="String">/foo:person/@id</xpath>

또는 org.apache.camel.builder.xml.XPathBuilder 로거에서 TRACE 수준 로깅을 활성화하도록 로깅 시스템을 구성할 수 있습니다.

네임스페이스 로깅이 활성화되면 처리된 각 메시지에 대해 다음과 같은 로그 메시지가 표시됩니다.

2012-01-16 13:23:45,878 [stSaxonWithFlag] INFO  XPathBuilder  -
Namespaces discovered in message: {xmlns:a=[http://apache.org/camel],
DEFAULT=[http://apache.org/default],
xmlns:b=[http://apache.org/camelA, http://apache.org/camelB]}

32.3. Cryostat Cryostat

32.3.1. 매개변수 바인딩 주석

Apache Camel 8080 통합을 사용하여 Java 8080에서 메서드를 호출할 때 @XPath 주석을 사용하여 교환에서 값을 추출하고 메서드 매개 변수에 바인딩할 수 있습니다.

예를 들어 AccountService 오브젝트에서 credit 메서드를 호출하는 다음 경로 조각을 고려하십시오.

from("queue:payments")
    .beanRef("accountService","credit")
    ...

credit 메서드는 매개 변수 바인딩 주석을 사용하여 메시지 본문에서 관련 데이터를 추출하고 다음과 같이 매개 변수에 삽입합니다.

public class AccountService {
    ...
    public void credit(
            @XPath("/transaction/transfer/receiver/text()") String name,
            @XPath("/transaction/transfer/amount/text()") String amount
            )
    {
        ...
    }
    ...
}

자세한 내용은 고객 포털 Apache Camel 개발 가이드 의 Cryostat 통합을 참조하십시오.

32.3.2. 네임스페이스

표 32.1. “@XPath에 대해 사전 정의된 네임스페이스” 은 Cryostat에 대해 사전 정의된 네임스페이스를 표시합니다. @XPath 주석에 표시되는 Cryostat 표현식 에서 이러한 네임스페이스 접두사를 사용할 수 있습니다.

표 32.1. @XPath에 대해 사전 정의된 네임스페이스

32.3.3. 사용자 정의 네임스페이스

@NamespacePrefix 주석을 사용하여 사용자 지정 XML 네임스페이스를 정의할 수 있습니다. @NamespacePrefix 주석을 호출하여 @XPath 주석의 namespace 인수 초기화합니다. 그런 다음 @NamespacePrefix 에서 정의한 네임스페이스를 @XPath 주석의 표현식 값에 사용할 수 있습니다.

예를 들어, 접두사인 ex 를 사용자 지정 네임스페이스인 http://fusesource.com/examples 와 연결하려면 다음과 같이 @XPath 주석을 호출합니다.

public class AccountService {
  ...
  public void credit(
    @XPath(
      value = "/ex:transaction/ex:transfer/ex:receiver/text()",
      namespaces = @NamespacePrefix( prefix = "ex", uri = "http://fusesource.com/examples"
      )
    ) String name,
    @XPath(
      value = "/ex:transaction/ex:transfer/ex:amount/text()",
      namespaces = @NamespacePrefix( prefix = "ex", uri = "http://fusesource.com/examples"
      )
    ) String amount,
  )
  {
    ...
  }
  ...
}

32.4. Cryostat 빌더

32.4.1. 개요

org.apache.camel.builder.xml.XPathBuilder 클래스를 사용하면 exchange와 독립적으로 Cryostat 표현식을 평가할 수 있습니다. 즉, 모든 소스의 XML 조각이 있는 경우 Cryostat Builder 를 사용하여 XML 조각에서 Cryostat 표현식을 평가할 수 있습니다.

32.4.2. 일치하는 표현식

matches() 메서드를 사용하여 지정된 Cryostat 표현식과 일치하는 하나 이상의 XML 노드를 찾을 수 있는지 확인합니다. Cryostat Builder 를 사용하여 Cryostat 식과 일치하는 기본 구문은 다음과 같습니다.

boolean matches = XPathBuilder
                    .xpath("Expression")
                    .matches(CamelContext, "XMLString");

여기서 지정된 식인 Expression 은 XML 조각, XMLString, 결과가 true와 일치하는 하나 이상의 노드가 발견되면 true에 대해 평가됩니다. 예를 들어 다음 예제에서는 true 를 반환하는데, 이는 Cryostat 표현식이 xyz 특성에서 일치하는 항목을 찾기 때문에 true를 반환합니다.

boolean matches = XPathBuilder
                    .xpath("/foo/bar/@xyz")
                    .matches(getContext(), "<foo><bar xyz='cheese'/></foo>"));

32.4.3. 표현식 평가

evaluate() 메서드를 사용하여 지정된 Cryostat 표현식과 일치하는 첫 번째 노드의 내용을 반환합니다. Cryostat Builder 를 사용하여 Cryostat 식을 평가하는 기본 구문은 다음과 같습니다.

String nodeValue = XPathBuilder
                    .xpath("Expression")
                    .evaluate(CamelContext, "XMLString");

필요한 형식을 evaluate() 의 두 번째 인수로 전달하여 결과 유형을 지정할 수도 있습니다. 예를 들면 다음과 같습니다.

String name = XPathBuilder
                   .xpath("foo/bar")
                   .evaluate(context, "<foo><bar>cheese</bar></foo>", String.class);
Integer number = XPathBuilder
                   .xpath("foo/bar")
                   .evaluate(context, "<foo><bar>123</bar></foo>", Integer.class);
Boolean bool = XPathBuilder
                   .xpath("foo/bar")
                   .evaluate(context, "<foo><bar>true</bar></foo>", Boolean.class);

32.5. Saxon 활성화

32.5.1. 사전 요구 사항

Saxon 구문 분석기를 사용하기 위한 전제 조건은 camel-saxon 아티팩트에 종속성을 추가하는 것입니다(Maven POM에 이 종속성을 추가하거나 Maven POM을 사용하는 경우 또는 camel-saxon-2.23.2.fuse-790054-redhat-00001.jar 파일을 클래스 경로에 추가).

32.5.2. Java DSL에서 Saxon 구문 분석기 사용

Java DSL에서 Saxon 구문 분석기를 활성화하는 가장 간단한 방법은 saxon() fluent 빌더 메서드를 호출하는 것입니다. 예를 들어 다음 예와 같이 Saxon 구문 분석기를 호출할 수 있습니다.

// Java
// create a builder to evaluate the xpath using saxon
XPathBuilder builder = XPathBuilder.xpath("tokenize(/foo/bar, '_')[2]").saxon();

// evaluate as a String result
String result = builder.evaluate(context, "<foo><bar>abc_def_ghi</bar></foo>");

32.5.3. XML DSL에서 Saxon 구문 분석기 사용

XML DSL에서 Saxon 구문 분석기를 활성화하는 가장 간단한 방법은 xpath 요소에서 saxon 속성을 true로 설정하는 것입니다. 예를 들어 다음 예와 같이 Saxon 구문 분석기를 호출할 수 있습니다.

<xpath saxon="true" resultType="java.lang.String">current-dateTime()</xpath>

32.5.4. Saxon을 사용한 프로그래밍

애플리케이션 코드에서 Saxon XML 구문 분석기를 사용하려면 다음 코드를 사용하여 명시적으로 Saxon transformer 팩토리 인스턴스를 생성할 수 있습니다.

// Java
import javax.xml.transform.TransformerFactory;
import net.sf.saxon.TransformerFactoryImpl;
...
TransformerFactory saxonFactory = new net.sf.saxon.TransformerFactoryImpl();

반면 generic CryostatP API를 사용하여 transformer 팩토리 인스턴스를 생성하려면 먼저 ESBInstall/etc/system.properties 파일에서 javax.xml.transform.TransformerFactory 속성을 설정해야 합니다.

javax.xml.transform.TransformerFactory=net.sf.saxon.TransformerFactoryImpl

그런 다음 일반 CryostatP API를 사용하여 다음과 같이 Saxon 팩토리를 인스턴스화할 수 있습니다.

// Java
import javax.xml.transform.TransformerFactory;
...
TransformerFactory factory = TransformerFactory.newInstance();

애플리케이션이 Saxon을 사용하는 타사 라이브러리에 종속되는 경우 두 번째 일반적인 접근 방식을 사용해야 할 수 있습니다.

참고

Saxon 라이브러리는 OSGi 번들인 net.sf.saxon/saxon9he 로 컨테이너에 설치해야 합니다(일반적으로 기본적으로 설치됨). 7.1 이전 버전의 Fuse ESB에서는 일반 CryostatP API를 사용하여 Saxon을 로드할 수 없습니다.

32.6. 표현식

32.6.1. 결과 유형

기본적으로 Cryostat 표현식은 org.w3c.dom.NodeList 유형의 하나 이상의 XML 노드 목록을 반환합니다. 그러나 형식 변환기 메커니즘을 사용하여 결과를 다른 형식으로 변환할 수 있습니다. Java DSL에서는 xpath() 명령의 두 번째 인수에 결과 유형을 지정할 수 있습니다. 예를 들어 Cryostat 표현식의 결과를 문자열로 반환하려면 다음을 수행합니다.

xpath("/person/name/text()", String.class)

XML DSL에서는 다음과 같이 resultType 속성에 결과 유형을 지정할 수 있습니다.

<xpath resultType="java.lang.String">/person/name/text()</xpath>

32.6.2. 위치 경로의 패턴

다음 패턴을 사용하여 location path로 이동할 수 있습니다.

/people/person

기본 위치 경로는 특정 요소의 중첩된 위치를 지정합니다. 즉, 이전 위치 경로는 다음 XML 조각의 person 요소와 일치합니다.

<people>
  <person>...</person>
</people>

이 기본 패턴은 people 요소 내부에 두 개 이상의 person 요소가 있는 경우 이 기본 패턴을 여러 개의 노드 Cryostat와 일치시킬 수 있습니다.

/name/text()
요소 내부의 텍스트에 액세스하려는 경우 / text () 를 위치 경로에 추가합니다. 그렇지 않으면 노드에 요소의 시작 및 끝 태그가 포함됩니다(노드를 문자열로 변환할 때 이러한 태그가 포함됩니다).
/person/telephone/@isDayTime

특성의 값을 선택하려면 AttributeName 구문을 사용합니다. @AttributeName. 예를 들어 이전 위치 경로는 다음 XML 조각에 적용할 때 true 를 반환합니다.

<person>
  <telephone isDayTime="true">1234567890</telephone>
</person>
*
지정된 범위의 모든 요소와 일치하는 와일드카드입니다. 예를 들어 /people/person/\*사람의 모든 자식 요소와 일치합니다.
@*
일치하는 요소의 모든 특성과 일치하는 와일드카드입니다. 예를 들어 / person/name/@\* 는 일치하는 모든 name 요소의 모든 특성과 일치합니다.
//

모든 중첩 수준의 위치 경로와 일치합니다. 예를 들어 //name 패턴은 다음 XML 조각에서 강조 표시된 모든 name 요소와 일치합니다.

<invoice>
  <person>
    <name .../>
  </person>
</invoice>
<person>
  <name .../>
</person>
<name .../>
..
현재 컨텍스트 노드의 부모를 선택합니다. 현재 컨텍스트 노드가 상위가 없는 문서 루트이므로 일반적으로 Apache Camel Cryostat 언어에서는 유용하지 않습니다.
node()
모든 종류의 노드와 일치합니다.
text()
텍스트 노드와 일치합니다.
comment()
주석 노드와 일치합니다.
processing-instruction()
processing-instruction 노드를 일치시킵니다.

32.6.3. 서술자 필터

대괄호로 대괄호로 묶어 위치 경로와 일치하는 노드 세트를 필터링할 수 있습니다. [Predicate]. 예를 들어, N ]을 위치 경로에 추가하여 일치 목록에서N th 노드를 선택할 수 있습니다. 다음 표현식은 일치하는 첫 번째 person 요소를 선택합니다.

/people/person[1]

다음 표현식은 두 번째-last person 요소를 선택합니다.

/people/person[last()-1]

특성 값을 테스트하여 특정 특성 값이 있는 요소를 선택할 수 있습니다. 다음 표현식은 surname 속성이 Strachan 또는 Davies인 name 요소를 선택합니다.

/person/name[@surname="Strachan" or @surname="Davies"]

연산자와 ,not() 중 하나를 사용하여 서술자 표현식을 결합할 수 있으며, 비교기를 사용하여 식을 비교할 수 있습니다. = ! = , > , >= , >= , < , , Cryostat (실실에서 더 적은 기호는 < 엔티티로 대체되어야 ) 서술자 필터에서 Cryostat 함수를 사용할 수도 있습니다.

32.6.4. Axes

XML 문서의 구조를 고려할 때 루트 요소에는 하위 시퀀스가 포함되어 있으며 일부 자식 요소에는 추가 하위 요소가 포함됩니다. 이 방법으로 중첩된 요소가 자식 관계에 의해 함께 연결되는 경우 전체 XML 문서에는 트리 구조가 있습니다. 이제 이 요소 트리에서 특정 노드를 선택하는 경우( 컨텍스트 노드라고 함) 선택한 노드를 기준으로 트리의 다른 부분을 참조할 수 있습니다. 예를 들어 컨텍스트 노드의 하위 노드, 컨텍스트 노드의 부모 또는 컨텍스트 노드(형제 노드)와 동일한 부모를 공유하는 모든 노드를참조할 수 있습니다.

Cryostat 은 현재 컨텍스트 노드를 기준으로 노드 트리의 특정 부분으로 검색을 제한하여 일치하는 노드 범위를 지정하는 데 사용됩니다. 축은 구문을 사용하여 일치시킬 노드 이름에 접두사로 연결되어 있습니다. 즉, < matchingNode > 구문을 사용합니다. 예를 들어 child:: 축을 사용하여 다음과 같이 현재 컨텍스트 노드의 자식을 검색할 수 있습니다.

/invoice/items/child::item

child::item 의 컨텍스트 노드는 경로 /invoice/ items .에서 선택한 항목 요소입니다. child:: axis는 검색을 컨텍스트 노드 항목의 하위 항목으로 제한하여 자식:: item 이 이름이 지정된 항목의 하위 항목과 일치하도록 합니다. 실제로 child:: 축은 기본 축이므로 앞의 예제를 다음과 같이 작성할 수 있습니다.

/invoice/items/item

그러나 몇 가지 다른 축(all)이 있고, 그 중 일부는 이미 축약된 형태로 표시됩니다. @특성:: 의 약어이며 //하위 항목 또는 자체:: 의 약어입니다. 전체 축 목록은 다음과 같습니다(자세한 내용은 아래 참조 참조 참조).

  • ancestor
  • ancestor-또는-self
  • attribute
  • child
  • descendant
  • descendant-or-self
  • 팔로우
  • Next-sibling
  • 네임스페이스
  • 상위
  • 이전 버전
  • preceding-sibling
  • self

32.6.5. 함수

Cryostat는 서술자를 평가할 때 유용할 수 있는 작은 표준 함수 세트를 제공합니다. 예를 들어 노드 세트에서 마지막으로 일치하는 노드를 선택하려면 다음과 같이 last() 함수를 사용하여 노드 세트의 마지막 노드의 인덱스를 반환할 수 있습니다.

/people/person[last()]

앞의 예제에서 시퀀스에서 마지막 person 요소를 선택합니다(문서 순서대로).

Cryostat가 제공하는 모든 기능에 대한 자세한 내용은 아래 참조를 참조하십시오.

32.6.6. reference

Cryostat 문법에 대한 자세한 내용은 XML 경로 언어, 버전 1.0 사양을 참조하십시오.

32.7. 서술자

32.7.1. 기본 서술자

서술자가 filter() 프로세서에 대한 인수로 또는 when() 절의 인수로 간주되는 컨텍스트에서 Java DSL 또는 XML DSL에서 xpath 를 사용할 수 있습니다.

예를 들어 다음 경로는 수신 메시지를 필터링하여 /person/city 요소에 값이 포함된 경우에만 message를 전달하도록 허용합니다.

from("direct:tie")
    .filter().xpath("/person/city = 'London'").to("file:target/messages/uk");

다음 경로는 when() 절에서 Cryostat 서술자를 평가합니다.

from("direct:tie")
    .choice()
        .when(xpath("/person/city = 'London'")).to("file:target/messages/uk")
        .otherwise().to("file:target/messages/others");

32.7.2. Cryostat 서술자 Operator

Cryostat 언어는 표 32.2. “Cryostat 언어의 Operator” 에 표시된 대로 표준 Cryostat 서술자 연산자를 지원합니다.

표 32.2. Cryostat 언어의 Operator

Operator설명

=

동일.

!=

같지 않음.

>

보다 큼.

>=

크거나 같음.

<

보다 적습니다.

작거나 같음.

두 서술자를 논리 및 와 결합합니다.

또는

논리 포함 또는 두 서술자를 결합합니다.

not()

negate 서술자 인수입니다.

32.8. 변수 및 함수 사용

32.8.1. 경로에서 변수 평가

경로 내에서 Cryostat 표현식을 평가할 때 Cryostat 변수를 사용하여 현재 교환 내용과 O/S 환경 변수 및 Java 시스템 속성에 액세스할 수 있습니다. 변수 값에 액세스하는 구문은 XML 네임스페이스를 통해 변수에 액세스하는 경우 $VarName 또는 $Prefix: VarName 입니다.

예를 들어 In 메시지의 본문에 $in:body 로 액세스하고 In 메시지의 헤더 값은 $in:HeaderName 으로 액세스할 수 있습니다. O/S 환경 변수는 $env:EnvVar 로 액세스할 수 있으며 Java 시스템 속성은 $system:SysVar 로 액세스할 수 있습니다.

다음 예에서 첫 번째 경로는 / person/city 요소의 값을 추출하여 city 헤더에 삽입합니다. 두 번째 경로 필터는 $in:city = 'London' 을 사용하여 교환합니다. 여기서 $in:city 변수가 city 헤더 값으로 교체됩니다.

from("file:src/data?noop=true")
    .setHeader("city").xpath("/person/city/text()")
    .to("direct:tie");

from("direct:tie")
    .filter().xpath("$in:city = 'London'").to("file:target/messages/uk");

32.8.2. 경로에서 함수 평가

표준 Cryostat 함수 외에도 Cryostat 언어는 추가 함수를 정의합니다. 이러한 추가 기능( 표 32.4. “Cryostat 사용자 정의 기능”에 나열된)은 기본 교환에 액세스하거나, 간단한 표현식을 평가하거나, Apache Camel 속성 자리 표시자 구성 요소에서 속성을 검색하는 데 사용할 수 있습니다.

예를 들어 다음 예제에서는 in:header() 함수와 in:body() 함수를 사용하여 기본 교환에서 헤드와 본문에 액세스합니다.

from("direct:start").choice()
  .when().xpath("in:header('foo') = 'bar'").to("mock:x")
  .when().xpath("in:body() = '<two/>'").to("mock:y")
  .otherwise().to("mock:z");

이러한 함수와 해당 in:HeaderName 또는 in:body 변수 간의 유사성을 확인합니다. 함수에는 in:body 가 아니라 in:header('HeaderName') 대신 in:header( 'HeaderName ' ) 및 in:body() 의 구문이 약간 다릅니다.

32.8.3. CryostatBuilder에서 변수 평가

Cryostat Builder 클래스를 사용하여 평가되는 표현식에서 변수를 사용할 수도 있습니다. 이 경우 평가할 교환 개체가 없기 때문에 $in:body 또는 $in:HeaderName 과 같은 변수를 사용할 수 없습니다. 그러나 변수 (이름,) fluent 빌더 방법을 사용하여 인라인으로 정의된 변수 를 사용할 수 있습니다.

예를 들어 다음 CryostatBuilder 구성은 $test 변수를 평가하며, 이 변수는ournon : 값을 갖도록 정의됩니다.

String var = XPathBuilder.xpath("$test")
               .variable("test", "London")
               .evaluate(getContext(), "<name>foo</name>");

이 방식으로 정의된 변수는 글로벌 네임스페이스에 자동으로 입력됩니다(예: 변수 $test 에서는 접두사를 사용하지 않음).

32.9. 변수 네임스페이스

32.9.1. 네임스페이스 테이블

표 32.3. “Cryostat 변수 네임스페이스” 다양한 네임스페이스 접두사와 연결된 네임스페이스 URI를 표시합니다.

표 32.3. Cryostat 변수 네임스페이스

네임스페이스 URI접두사설명

http://camel.apache.org/schema/spring

없음

기본 네임스페이스(네임스페이스 접두사가 없는 변수와 연결됨).

http://camel.apache.org/xml/in/

in

현재 교환의 In 메시지의 헤더 또는 본문을 참조하는 데 사용됩니다.

http://camel.apache.org/xml/out/

out

현재 교환의 아웃 메시지의 헤더 또는 본문을 참조하는 데 사용됩니다.

http://camel.apache.org/xml/functions/

함수

일부 사용자 지정 함수를 참조하는 데 사용됩니다.

http://camel.apache.org/xml/variables/environment-variables

env

O/S 환경 변수를 참조하는 데 사용됩니다.

http://camel.apache.org/xml/variables/system-properties

system

Java 시스템 속성을 참조하는 데 사용됩니다.

http://camel.apache.org/xml/variables/exchange-property

정의되지 않음

교환 속성을 참조하는 데 사용됩니다. 이 네임스페이스에 대한 자체 접두사를 정의해야 합니다.

32.10. 함수 참조

32.10.1. 사용자 지정 함수 테이블

표 32.4. “Cryostat 사용자 정의 기능” Apache Camel Cryostat 표현식에서 사용할 수 있는 사용자 지정 함수를 표시합니다. 이러한 함수는 표준 Cryostat 함수 외에도 사용할 수 있습니다.

표 32.4. Cryostat 사용자 정의 기능

함수설명

in:body()

메시지 본문을 반환합니다.

in:header(HeaderName)

name, HeaderName 이 포함된 In 메시지 헤더를 반환합니다.

out:body()

외부 메시지 본문을 반환합니다.

out:header(HeaderName)

name, HeaderName 을 사용하여 Out 메시지 헤더를 반환합니다.

function:properties(PropKey)

PropKey 키를 사용하여 속성을 조회합니다.

function:simple(SimpleExp)

지정된 단순 표현식 SimpleExp 를 평가합니다.

33장. XQuery

33.1. 개요

XQuery는 원래 XML 형식으로 데이터베이스에 저장된 데이터의 쿼리 언어로 고안되었습니다. XQuery 언어를 사용하면 메시지가 XML 형식일 때 현재 메시지의 일부를 선택할 수 있습니다. XQuery는 Cryostat 언어의 상위 집합이므로 유효한 모든 Cryostat 표현식도 유효한 XQuery 표현식입니다.

33.2. Java 구문

XQuery 표현식을 여러 가지 방법으로 xquery() 에 전달할 수 있습니다. 간단한 표현식의 경우 XQuery 표현식을 문자열(java.lang.String)으로 전달할 수 있습니다. 더 긴 XQuery 표현식의 경우 식을 파일에 저장하는 것을 선호할 수 있습니다. 이 표현식은 java.io.File 인수 또는 java.net.URL 인수를 오버로드된 xquery() 메서드에 전달하여 참조할 수 있습니다. XQuery 표현식은 메시지 콘텐츠에 암시적으로 작동하고 그 결과로 노드 세트를 반환합니다. 컨텍스트에 따라 반환 값은 서술자(빈 노드 세트가 false로 해석되는 경우) 또는 표현식으로 해석됩니다.

33.3. Saxon 모듈 추가

경로에서 XQuery를 사용하려면 예 33.1. “camel-saxon 종속성 추가” 에 표시된 것처럼 camel-saxon 에 대한 종속성을 프로젝트에 추가해야 합니다.

예 33.1. camel-saxon 종속성 추가

<!-- Maven POM File -->
...
<dependencies>
  ...
  <dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-saxon</artifactId>
    <version>${camel-version}</version>
  </dependency>
  ...
</dependencies>

33.4. Camel on EAP 배포

camel-saxon 구성 요소는 Red Hat JBoss EAP(JBoss Enterprise Application Platform) 컨테이너에 간단한 배포 모델을 제공하는 EAP의 Camel(Wildfly Camel) 프레임워크에서 지원합니다.

33.5. 정적 가져오기

애플리케이션 코드에서 xquery() 정적 메서드를 사용하려면 Java 소스 파일에 다음 import 문을 포함합니다.

import static org.apache.camel.component.xquery.XQueryBuilder.xquery;

33.6. 변수

표 33.1. “XQuery 변수” XQuery를 사용할 때 액세스할 수 있는 변수를 나열합니다.

표 33.1. XQuery 변수

Variable유형설명

exchange

교환

현재 교환

in.body

개체

IN 메시지의 본문

out.body

개체

OUT 메시지의 본문

in.headers.key

개체

키가 key인 IN 메시지 헤더

out.headers.key

개체

키가 key인 OUT 메시지 헤더

key

개체

키가 인 교환 속성

33.7. 예제

예 33.2. “XQuery를 사용하는 경로” XQuery를 사용하는 경로를 표시합니다.

예 33.2. XQuery를 사용하는 경로

<camelContext>
  <route>
    <from uri="activemq:MyQueue"/>
    <filter>
      <language langauge="xquery">/foo:person[@name='James']</language>
      <to uri="mqseries:SomeOtherQueue"/>
    </filter>
  </route>
</camelContext>

III 부. 고급 Camel 프로그래밍

이 가이드에서는 Apache Camel API 사용 방법을 설명합니다.

34장. 메시지 형식 이해

초록

Apache Camel로 프로그래밍을 시작하기 전에 메시지와 메시지 교환을 모델링하는 방법을 명확하게 이해해야 합니다. Apache Camel은 많은 메시지 형식을 처리할 수 있으므로 기본 메시지 유형은 추상 형식으로 설계되었습니다. Apache Camel은 메시지 본문 및 메시지 헤더에 따라 데이터 형식에 액세스하고 변환하는 데 필요한 API를 제공합니다.

34.1. 교환

34.1.1. 개요

교환 오브젝트 는 수신된 메시지를 캡슐화하고 연결된 메타데이터(배치 속성포함)를 저장하는 래퍼입니다. 또한 현재 메시지가 생산자 엔드포인트에 디스패치되는 경우 교환은 응답을 유지할 임시 슬롯( Out 메시지)을 제공합니다.

Apache Camel의 교환의 중요한 기능은 지연 메시지 생성을 지원한다는 것입니다. 이는 메시지에 대한 명시적 액세스가 필요하지 않은 경로의 경우 상당한 최적화를 제공할 수 있습니다.

그림 34.1. 경로를 통해 오브젝트 전달 교환

경로를 통해 전달되는 개체 교환

그림 34.1. “경로를 통해 오브젝트 전달 교환” 경로를 통과하는 교환 오브젝트를 표시합니다. 경로 컨텍스트에서 교환 오브젝트는 Processor.process() 메서드의 인수로 전달됩니다. 즉, 교환 오브젝트는 소스 끝점, 대상 끝점 및 그 사이의 모든 프로세서에 직접 액세스할 수 있습니다.

34.1.2. 교환 인터페이스

org.apache.camel.Exchange 인터페이스는 예 34.1. “교환 방법” 와 같이 InOut 메시지에 액세스하는 방법을 정의합니다.

예 34.1. 교환 방법

// Access the In message
Message getIn();
void    setIn(Message in);

// Access the Out message (if any)
Message getOut();
void    setOut(Message out);
boolean hasOut();

// Access the exchange ID
String  getExchangeId();
void    setExchangeId(String id);

교환 인터페이스의 방법에 대한 자세한 내용은 43.1절. “교환 인터페이스” 을 참조하십시오.

34.1.3. 메시지 생성 지연

Apache Camel은 In,OutFault 메시지 지연 생성을 지원합니다. 즉, getIn() 또는 getOut()을 호출하여 액세스하려고 할 때까지 메시지 인스턴스가 생성되지 않습니다. lazy 메시지 생성 의미 체계는 org.apache.camel.impl.DefaultExchange 클래스에 의해 구현됩니다.

no-argument 접근자(getIn() 또는 getOut()) 중 하나를 호출하거나 부울 인수를 true (즉, getIn(true) 또는 getOut(true)로 호출하면 기본 메서드 구현에서 새 메시지 인스턴스를 생성합니다.

false (즉, getIn(false) 또는 getOut(false)와 같은 부울 인수를 사용하여 접근자를 호출하면 기본 메서드 구현에서 현재 메시지 값을 반환합니다.[1]

34.1.4. 교환 ID 생성 지연

Apache Camel은 교환 ID의 지연 생성을 지원합니다. 모든 교환에서 getExchangeId() 를 호출하여 해당 교환 인스턴스에 대한 고유 ID를 가져올 수 있지만 실제로 메서드를 호출하는 경우에만 ID가 생성됩니다. 이 메서드의 DefaultExchange.getExchangeId() 구현은 ID 생성을 CamelContext 에 등록된 UUID 생성기에 위임합니다.

CamelContext 에 UUID 생성기를 등록하는 방법에 대한 자세한 내용은 34.4절. “내장된 UUID 생성기” 을 참조하십시오.

34.2. 메시지

34.2.1. 개요

메시지 오브젝트는 다음 추상 모델을 사용하여 메시지를 나타냅니다.

  • 메시지 본문
  • 메시지 헤더
  • 메시지 첨부 파일

메시지 본문과 메시지 헤더는 임의의 유형( 개체형식으로 선언됨)일 수 있으며 메시지 첨부 파일은 임의의 MIME 유형을 포함할 수 있는 javax.activation.DataHandler 유형으로 선언됩니다. 메시지 내용을 구체적으로 표현해야 하는 경우 형식 변환기 메커니즘을 사용하여 본문과 헤더를 다른 유형으로 변환할 수 있으며 마샬링 및 비마일링 메커니즘을 사용할 수 있습니다.If you need to obtain a specific representation of the message contents, you can convert the body and headers to another type using the type converter mechanism and, possibly, using the marshalling and unmarshalling mechanism.

Apache Camel 메시지의 한 가지 중요한 기능은 메시지 본문 및 헤더의 지연 생성 을 지원하는 것입니다. 경우에 따라 메시지를 전혀 구문 분석할 필요 없이 경로를 통과할 수 있습니다.

34.2.2. 메시지 인터페이스

org.apache.camel.Message 인터페이스는 예 34.2. “메시지 인터페이스” 와 같이 메시지 본문, 메시지 헤더 및 메시지 첨부 파일에 액세스하는 방법을 정의합니다.

예 34.2. 메시지 인터페이스

// Access the message body
Object getBody();
<T> T  getBody(Class<T> type);
void   setBody(Object body);
<T> void setBody(Object body, Class<T> type);

// Access message headers
Object getHeader(String name);
<T> T  getHeader(String name, Class<T> type);
void   setHeader(String name, Object value);
Object removeHeader(String name);
Map<String, Object> getHeaders();
void setHeaders(Map<String, Object> headers);

// Access message attachments
javax.activation.DataHandler getAttachment(String id);
java.util.Map<String, javax.activation.DataHandler> getAttachments();
java.util.Set<String> getAttachmentNames();
void addAttachment(String id, javax.activation.DataHandler content)

// Access the message ID
String getMessageId();
void   setMessageId(String messageId);

메시지 인터페이스의 방법에 대한 자세한 내용은 44.1절. “메시지 인터페이스” 을 참조하십시오.

34.2.3. 본문, 헤더 및 첨부 파일의 지연 생성

Apache Camel은 본문, 헤더 및 첨부 파일의 지연 생성을 지원합니다. 즉, 메시지 본문, 메시지 헤더 또는 메시지 첨부를 나타내는 개체는 필요할 때까지 생성되지 않습니다.

예를 들어 In 메시지에서 foo 메시지 헤더에 액세스하는 다음 경로를 고려하십시오.

from("SourceURL")
    .filter(header("foo")
    .isEqualTo("bar"))
    .to("TargetURL");

이 경로에서 SourceURL 에서 참조하는 구성 요소가 지연 생성을 지원한다고 가정하면 header("foo") 호출이 실행될 때까지 In 메시지 헤더가 실제로 구문 분석되지 않습니다. 이 시점에서 기본 메시지 구현은 헤더를 구문 분석하고 헤더 맵을 채웁니다. 메시지 본문 은 경로 끝에 도달할 때까지 to("TargetURL") 호출에서 구문 분석되지 않습니다. 이 시점에서 본문은 대상 끝점인 TargetURL 에 작성하는 데 필요한 형식으로 변환됩니다.

본문, 헤더 및 첨부 파일을 채우기 전에 가능한 마지막 순간까지 기다리면 불필요한 유형 변환을 피할 수 있습니다. 경우에 따라 구문 분석을 완전히 방지할 수 있습니다. 예를 들어 경로에 메시지 헤더에 대한 명시적 참조가 없는 경우 메시지는 헤더를 구문 분석하지 않고 경로를 통과할 수 있습니다.

지연 생성이 실제로 구현되었는지 여부는 기본 구성 요소 구현에 따라 다릅니다. 일반적으로 지연 생성은 메시지 본문, 메시지 헤더 또는 메시지 첨부 파일을 생성하는 경우 비용이 많이 듭니다. 지연 생성을 지원하는 메시지 유형을 구현하는 방법에 대한 자세한 내용은 44.2절. “메시지 인터페이스 구현” 을 참조하십시오.

34.2.4. 메시지 ID 생성 지연

Apache Camel은 메시지 ID의 지연 생성을 지원합니다. 즉, 메시지 ID는 실제로 getMessageId() 메서드를 호출할 때만 생성됩니다. 이 메서드의 DefaultExchange.getExchangeId() 구현은 ID 생성을 CamelContext 에 등록된 UUID 생성기에 위임합니다.

일부 엔드포인트 구현에서는 엔드포인트가 고유한 메시지 ID가 필요한 프로토콜을 구현하는 경우 getMessageId() 메서드를 암시적으로 호출합니다. 특히 JMS 메시지에는 일반적으로 고유한 메시지 ID가 포함된 헤더가 포함되어 있으므로 JMS 구성 요소는 getMessageId() 를 자동으로 호출하여 메시지 ID를 가져옵니다(JMS 엔드포인트에서 messageIdEnabled 옵션에 의해 제어됨).

CamelContext 에 UUID 생성기를 등록하는 방법에 대한 자세한 내용은 34.4절. “내장된 UUID 생성기” 을 참조하십시오.

34.2.5. 초기 메시지 형식

In 메시지의 초기 형식은 소스 끝점에 의해 결정되며 Out 메시지의 초기 형식은 대상 끝점에 따라 결정됩니다. 기본 구성 요소에서 lazy 생성을 지원하는 경우 애플리케이션에서 명시적으로 액세스할 때까지 메시지는 구문 해제된 상태로 유지됩니다. 대부분의 Apache Camel 구성 요소는 비교적 원시 형식의 message 본문을 생성합니다. 예를 들어 byte[], Cryostat Buffer,InputStream 또는 OutputStream 과 같은 유형을 사용하여 나타내는 메시지 본문을 생성합니다. 이렇게 하면 초기 메시지를 생성하는 데 필요한 오버헤드가 최소화됩니다. 더 정교한 메시지 형식이 필요한 경우 일반적으로 형식 변환기 또는 마샬링 프로세서에 의존합니다.

34.2.6. 유형 변환기

메시지의 초기 형식이 무엇인지는 중요하지 않습니다. 기본 제공 유형 변환기를 사용하여 메시지를 한 형식에서 다른 형식으로 쉽게 변환할 수 있기 때문입니다( 34.3절. “붙박임 유형”참조). Apache Camel API에는 유형 변환 기능을 노출하는 다양한 방법이 있습니다. 예를 들어 convertBodyTo(Class type) 메서드를 경로에 삽입하여 다음과 같이 In 메시지의 본문을 변환할 수 있습니다.

from("SourceURL").convertBodyTo(String.class).to("TargetURL");

여기서 In 메시지의 본문은 java.lang.String 으로 변환됩니다. 다음 예제에서는 In 메시지 본문의 끝에 문자열을 추가하는 방법을 보여줍니다.

from("SourceURL").setBody(bodyAs(String.class).append("My Special Signature")).to("TargetURL");

여기서 메시지 본문은 끝에 문자열을 추가하기 전에 문자열 형식으로 변환됩니다. 이 예에서 메시지 본문을 명시적으로 변환할 필요는 없습니다. 또는 다음을 수행할 수도 있습니다.

from("SourceURL").setBody(body().append("My Special Signature")).to("TargetURL");

여기서 append() 메서드는 인수를 추가하기 전에 메시지 본문을 문자열로 자동 변환합니다.

34.2.7. 메시지에 변환 메서드를 입력합니다.Type conversion methods in Message

org.apache.camel.Message 인터페이스는 유형 변환을 명시적으로 수행하는 몇 가지 메서드를 노출합니다.

  • getBody(Class<T> 유형) 메시지 본문을 유형 T 로 반환합니다.
  • getHeader(문자열 이름, Class<T> 유형) Cryostat-ECDHE-11 choosing the named header value as type, T.

지원되는 변환 유형의 전체 목록은 34.3절. “붙박임 유형” 을 참조하십시오.

34.2.8. XML로 변환

기본 제공 형식 변환기는 XML 형식으로의 변환도 지원합니다.In addition to support conversion between simple types (such as byte[], Cryostat Buffer,string, and so on), the built-in type converter also supports conversion to XML formats. 예를 들어 메시지 본문을 org.w3c.dom.Document 유형으로 변환할 수 있습니다. 이 변환은 전체 메시지를 구문 분석한 다음 XML 문서 구조를 나타내는 노드 트리를 생성해야 하므로 단순 변환보다 비용이 많이 듭니다. 다음 XML 문서 유형으로 변환할 수 있습니다.

  • org.w3c.dom.Document
  • javax.xml.transform.sax.SAXSource

XML 유형 변환에는 단순한 변환보다 더 적은 적용 가능성이 있습니다. 모든 메시지 본문이 XML 구조를 따르는 것은 아니므로 이 형식 변환이 실패할 수 있다는 점을 명심해야 합니다. 반면 라우터가 XML 메시지 유형을 독점적으로 처리하는 많은 시나리오가 있습니다.

34.2.9. 마샬링 및 unmarshalling

마샬링 은 높은 수준의 형식을 낮은 수준의 형식으로 변환해야 하며, unmarshalling 은 하위 수준 형식을 상위 수준 형식으로 변환하는 것입니다. 다음 두 프로세서는 경로에서 마샬링 또는 unmarshalling을 수행하는 데 사용됩니다.

  • marshal()
  • unmarshal()

예를 들어 파일에서 직렬화된 Java 오브젝트를 읽고 Java 오브젝트로 요약하려면 예 34.3. “Java 오브젝트 정리” 에 표시된 경로 정의를 사용할 수 있습니다.

예 34.3. Java 오브젝트 정리

from("file://tmp/appfiles/serialized")
    .unmarshal()
    .serialization()
    .<FurtherProcessing>
    .to("TargetURL");

34.2.10. 최종 메시지 형식

In 메시지가 경로 끝에 도달하면 대상 끝점에서 메시지 본문을 물리적 엔드포인트에 쓸 수 있는 형식으로 변환할 수 있어야 합니다. 소스 엔드포인트에 다시 도달하는 Out 메시지에도 동일한 규칙이 적용됩니다. 이 변환은 일반적으로 Apache Camel 유형 변환기를 사용하여 암시적으로 수행됩니다. 일반적으로 바이트[] 배열에서 InputStream 유형으로 변환하는 등 하위 수준 형식에서 다른 하위 수준 형식으로 변환하는 작업이 포함됩니다.

34.3. 붙박임 유형

34.3.1. 개요

이 섹션에서는 마스터 유형 변환기에서 지원하는 변환에 대해 설명합니다. 이러한 변환은 Apache Camel 코어에 빌드됩니다.

일반적으로 유형 변환기는 Message.getBody(Class<T> 유형) 또는 Message.getHeader(String name, Class<T > 유형) 과 같은 편의성 함수를 통해 호출됩니다. 마스터 유형 변환기를 직접 호출할 수도 있습니다. 예를 들어 교환 오브젝트인 exchange 가 있는 경우 예 34.4. “값을 문자열로 변환” 에 표시된 대로 지정된 값을 String 으로 변환할 수 있습니다.

예 34.4. 값을 문자열로 변환

org.apache.camel.TypeConverter tc = exchange.getContext().getTypeConverter();
String str_value = tc.convertTo(String.class, value);

34.3.2. 기본 유형 변환기

Apache Camel은 다음 기본 유형으로의 변환을 수행하는 기본 제공 유형 변환기를 제공합니다.

  • java.io.File
  • 문자열
  • byte[] and java.nio.ByteBuffer
  • java.io.InputStreamjava.io.OutputStream
  • java.io. Cryo stat 및 java.io.Writer
  • java.io.BufferedReader and java.io.BufferedWriter
  • java.io.StringReader

그러나 이러한 유형의 모든 유형이 상호 작용 가능한 것은 아닙니다. 기본 제공 변환기는 주로 파일문자열 유형에서 변환을 제공하는 데 중점을 둡니다. File 유형은 Reader,Writer, String Cryostat를 제외한 모든 이전 유형으로 변환할 수 있습니다. String 유형은 File,byte[], Cryostat Buffer ,Input Stream 또는 String Cryostat로 변환할 수 있습니다. 문자열 을 파일 이름으로 해석하여 문자열을 File 으로 변환합니다. 문자열,byte[] 및 Cryostat Buffer 의 trio는 완전히 상호 호환 가능합니다.

참고

현재 교환에서 Exchange.CHARSET_NAME 교환 속성을 설정하여 바이트[] 에서 문자열로, 그리고 String 에서 byte[] 로 변환하는 데 사용할 문자 인코딩을 명시적으로 지정할 수 있습니다. 예를 들어 UTF-8 문자 인코딩을 사용하여 변환을 수행하려면 exchange.setProperty("Exchange.CHARSET_NAME", "UTF-8") 를 호출합니다. 지원되는 문자 세트는 java.nio.charset.Charset 클래스에 설명되어 있습니다.

34.3.3. 컬렉션 유형 변환기

Apache Camel은 다음 컬렉션 유형으로의 변환을 수행하는 기본 제공 유형 변환기를 제공합니다.

  • Object[]
  • java.util.Set
  • java.util.List

이전 컬렉션 유형 간의 모든 변환이 지원됩니다.

34.3.4. 매핑 유형 변환기

Apache Camel은 다음 맵 유형으로의 변환을 수행하는 기본 제공 유형 변환기를 제공합니다.

  • java.util.Map
  • java.util.HashMap
  • java.util.Hashtable
  • java.util.Properties

이전 맵 유형도 java.util.Set 유형의 세트로 변환할 수 있습니다. 여기서 set 요소는 MapEntry<K,V > 유형입니다.

34.3.5. Cryostat 유형 컨버터

다음과 같은 Document Object Model(DOM) 유형으로 형식 변환을 수행할 수 있습니다.

  • org.w3c.dom.Document kafka- Cryostat-Enginevertible from byte[], string,java.io.File, and java.io.InputStream.
  • org.w3c.dom.Node
  • 문자열 에서 javax.xml.transform.dom.DOMSource Cryostat-ECDHEvertible.
  • byte[]문자열 에서 javax.xml.transform.Source Cryostat-ECDHEconvertible.

이전 192.0.2. 유형 간의 모든 변환이 지원됩니다.

34.3.6. SAX 유형 변환기

SAX 이벤트 기반 XML 구문 분석을 지원하는 javax.xml.transform.sax.SAXSource 유형으로 변환을 수행할 수도 있습니다(자세한 내용은 SAX 웹 사이트 참조). 다음 유형에서 SAXSource 로 변환할 수 있습니다.

  • 문자열
  • InputStream
  • 소스
  • StreamSource
  • CryostatSource

34.3.7. enum 유형 변환기

Camel은 형식을 열거 하기 위해 문자열 을 수행하기 위한 형식 변환기를 제공합니다. 여기서 문자열 값은 지정된 열거 클래스에서 일치하는 enum 상수로 변환됩니다(정합은 대소문자를 구분하지 않음). 이 유형 변환기는 메시지 본문을 변환하는 데 거의 필요하지 않지만 Apache Camel에서 특정 옵션을 선택하는 데 자주 사용됩니다.

예를 들어 로깅 수준 옵션을 설정할 때 다음 값인 INFOenum 상수로 변환됩니다.

<to uri="log:foo?level=INFO"/>

enum 형식 변환기는 대소문자를 구분하지 않으므로 다음 대안도 작동합니다.Because the enum type converter is case-insensitive, any of the following alternatives would also work:

<to uri="log:foo?level=info"/>
<to uri="log:foo?level=INfo"/>
<to uri="log:foo?level=InFo"/>

34.3.8. 사용자 정의 유형 변환기

Apache Camel을 사용하면 사용자 정의 유형 변환기를 구현할 수 있습니다. 사용자 정의 유형 변환기를 구현하는 방법에 대한 자세한 내용은 36장. 유형 전환 을 참조하십시오.

34.4. 내장된 UUID 생성기

34.4.1. 개요

Apache Camel을 사용하면 CamelContext 에서 UUID 생성기를 등록할 수 있습니다. 그런 다음 이 UUID 생성기는 Apache Camel이 고유한 ID 전환이 필요할 때마다 등록된 UUID 생성기가 호출되어 Exchange.getExchangeId()Message.getMessageId() 메서드에서 반환한 ID를 생성합니다.

예를 들어 애플리케이션의 일부가 ID를 36자(예: Websphere MQ)로 지원하지 않는 경우 기본 UUID 생성기를 교체할 수 있습니다. 또한 테스트를 위해 간단한 카운터( SimpleUuidGenerator참조)를 사용하여 ID를 생성하는 것이 편리합니다.

34.4.2. 제공된 UUID 생성기

코어에 제공되는 다음 UUID 생성기 중 하나를 사용하도록 Apache Camel을 구성할 수 있습니다.

  • org.apache.camel.impl.ActiveMQUuidGenerator Cryostat- (Default) 는 Apache ActiveMQ에서 사용하는 것과 동일한 ID 스타일을 생성합니다. 이 구현은 클라우드 컴퓨팅 (예: Google App Engine) 컨텍스트에서 금지되는 일부 JDK API를 사용하므로 모든 애플리케이션에 적합하지 않을 수 있습니다.
  • org.apache.camel.impl.SimpleUuidGenerator Cryostat-WITHimplements a simple counter ID, starting at 1. 기본 구현은 스레드로부터 안전하도록 java.util.concurrent.atomic.AtomicLong 유형을 사용합니다.
  • org.apache.camel.impl.JavaUuidGenerator Cryostat- functionimplements an ID based on the java.util.UUID type. java.util.UUID 가 동기화되므로 일부 고도의 동시 시스템의 성능에 영향을 미칠 수 있습니다.

34.4.3. 사용자 정의 UUID 생성기

사용자 지정 UUID 생성기를 구현하려면 예 34.5. “UuidGenerator Interface” 에 표시된 org.apache.camel.spi.UuidGenerator 인터페이스를 구현합니다. generateUuid() 는 고유한 ID 문자열을 반환하도록 구현되어야 합니다.

예 34.5. UuidGenerator Interface

// Java
package org.apache.camel.spi;

/**
 * Generator to generate UUID strings.
 */
public interface UuidGenerator {
    String generateUuid();
}

34.4.4. Java를 사용하여 UUID 생성기 지정

Java를 사용하여 기본 UUID 생성기를 교체하려면 현재 CamelContext 오브젝트에서 setUuidGenerator() 메서드를 호출합니다. 예를 들어 다음과 같이 현재 CamelContextSimpleUuidGenerator 인스턴스를 등록할 수 있습니다.

// Java
getContext().setUuidGenerator(new org.apache.camel.impl.SimpleUuidGenerator());
참고

setUuidGenerator() 메서드는 시작 중에 경로가 활성화되기 전에 호출되어야 합니다.

34.4.5. Spring을 사용하여 UUID 생성기 지정

Spring을 사용하여 기본 UUID 생성기를 교체하려면 Springans 요소를 사용하여 UUID 생성기 인스턴스를 생성하는 것입니다. camelContext 인스턴스가 생성되면 Spring 레지스트리를 자동으로 조회하여 org.apache.camel.spi.UuidGenerator. 예를 들어 다음과 같이 CamelContextSimpleUuidGenerator 인스턴스를 등록할 수 있습니다.

<beans ...>
  <bean id="simpleUuidGenerator"
        class="org.apache.camel.impl.SimpleUuidGenerator" />

  <camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
      ...
  </camelContext>
  ...
</beans>


[1] 활성 메서드가 없으면 반환된 값은 null 입니다.

35장. 프로세서 구현

초록

Apache Camel을 사용하면 사용자 지정 프로세서를 구현할 수 있습니다. 그런 다음 사용자 지정 프로세서를 경로에 삽입하여 경로를 통과할 때 교환 오브젝트에 대한 작업을 수행할 수 있습니다.

35.1. 처리 모델

35.1.1. 파이프라이닝 모델

파이프라이닝 모델은 5.4절. “파이프 및 필터” 에서 프로세서를 정렬하는 방법을 설명합니다. 파이프라이닝은 일련의 엔드포인트를 처리하는 가장 일반적인 방법입니다(프로덕션 끝점은 특수한 유형의 프로세서일 뿐입니다). 프로세서가 이러한 방식으로 정렬되면 그림 35.1. “파이프라이닝 모델” 에 표시된 대로 교환의 InOut 메시지가 처리됩니다.

그림 35.1. 파이프라이닝 모델

파이프라이닝 모델

파이프라인의 프로세서는 In 메시지가 요청과 유사하며 외부 메시지는 응답과 유사한 서비스처럼 보입니다. 사실, 비현실적 파이프라인에서 파이프라인의 노드는 CXF 구성 요소와 같은 웹 서비스 엔드포인트에 의해 구현되는 경우가 많습니다.

예를 들어 예 35.1. “Java DSL Pipeline” 는 두 프로세서, ProcessorA,ProcessorB 및 생산자 끝점인 TargetURI 의 시퀀스로 구성된 Java DSL 파이프라인을 보여줍니다.

예 35.1. Java DSL Pipeline

from(SourceURI).pipeline(ProcessorA, ProcessorB, TargetURI);

35.2. 간단한 프로세서 구현

35.2.1. 개요

이 섹션에서는 경로에서 다음 프로세서로 교환을 위임하기 전에 메시지 처리 논리를 실행하는 간단한 프로세서를 구현하는 방법을 설명합니다.

35.2.2. 프로세서 인터페이스

간단한 프로세서는 org.apache.camel.Processor 인터페이스를 구현하여 생성됩니다. 예 35.2. “프로세서 인터페이스” 에 표시된 대로 인터페이스는 교환 오브젝트를 처리하는 단일 메서드인 process() 를 정의합니다.

예 35.2. 프로세서 인터페이스

package org.apache.camel;

public interface Processor {
    void process(Exchange exchange) throws Exception;
}

35.2.3. 프로세서 인터페이스 구현

간단한 프로세서를 만들려면 Processor 인터페이스를 구현하고 process() 메서드에 대한 논리를 제공해야 합니다. 예 35.3. “간단한 프로세서 구현” 간단한 프로세서 구현의 개요를 보여줍니다.

예 35.3. 간단한 프로세서 구현

import org.apache.camel.Processor;

public class MyProcessor implements Processor {
    public MyProcessor() { }

    public void process(Exchange exchange) throws Exception
    {
        // Insert code that gets executed *before* delegating
        // to the next processor in the chain.
        ...
    }
}

process() 메서드의 모든 코드는 교환 개체가 체인의 다음 프로세서에 위임되기 전에 실행됩니다.

간단한 프로세서 내에서 메시지 본문 및 헤더 값에 액세스하는 방법에 대한 예제는 35.3절. “메시지 콘텐츠에 액세스” 를 참조하십시오.

35.2.4. 경로에 간단한 프로세서 삽입

process() DSL 명령을 사용하여 경로에 간단한 프로세서를 삽입합니다. 사용자 지정 프로세서의 인스턴스를 만든 다음 다음과 같이 이 인스턴스를 process() 메서드에 인수로 전달합니다.

org.apache.camel.Processor myProc = new MyProcessor();

from("SourceURL").process(myProc).to("TargetURL");

35.3. 메시지 콘텐츠에 액세스

35.3.1. 메시지 헤더에 액세스

일반적으로 메시지 헤더에는 라우터 서비스에서 헤더를 처리할 수 있으므로 라우터 관점에서 가장 유용한 메시지 콘텐츠가 포함됩니다. 헤더 데이터에 액세스하려면 먼저 교환 오브젝트(예: Exchange.getIn())에서 메시지를 가져온 다음 Message 인터페이스를 사용하여 개별 헤더(예: Message.getHeader()사용)를 검색해야 합니다.

예 35.4. “인증 헤더 액세스” Authorization 이라는 헤더 값에 액세스하는 사용자 지정 프로세서의 예를 보여줍니다. 이 예제에서는 exchangeHelper.getMandatoryHeader() 메서드를 사용하여 null 헤더 값을 테스트할 필요가 없습니다.

예 35.4. 인증 헤더 액세스

import org.apache.camel.*;
import org.apache.camel.util.ExchangeHelper;

public class MyProcessor implements Processor {
  public void process(Exchange exchange) {
    String auth = ExchangeHelper.getMandatoryHeader(
                      exchange,
                      "Authorization",
                      String.class
                  );
    // process the authorization string...
    // ...
  }
}

메시지 인터페이스에 대한 자세한 내용은 34.2절. “메시지” 을 참조하십시오.

35.3.2. 메시지 본문에 액세스

메시지 본문에도 액세스할 수 있습니다. 예를 들어 In 메시지 끝에 문자열을 추가하려면 예 35.5. “메시지 본문 액세스” 에 표시된 프로세서를 사용할 수 있습니다.

예 35.5. 메시지 본문 액세스

import org.apache.camel.*;
import org.apache.camel.util.ExchangeHelper;

public class MyProcessor implements Processor {
    public void process(Exchange exchange) {
        Message in = exchange.getIn();
        in.setBody(in.getBody(String.class) + " World!");
    }
}

35.3.3. 메시지 첨부 파일에 액세스

Message.getAttachment() 메서드 또는 Message.getAttachments() 메서드를 사용하여 메시지의 첨부 파일에 액세스할 수 있습니다. 자세한 내용은 예 34.2. “메시지 인터페이스”를 참조하십시오.

35.4. ExchangeHelper 클래스

35.4.1. 개요

org.apache.camel.util.ExchangeHelper 클래스는 프로세서를 구현할 때 유용한 메서드를 제공하는 Apache Camel 유틸리티 클래스입니다.

35.4.2. 끝점 확인

정적 resolveEndpoint() 메서드는 ExchangeHelper 클래스에서 가장 유용한 메서드 중 하나입니다. 프로세서 내에서 새 끝점 인스턴스를 만드는 데 사용할 수 있습니다.

예 35.6. resolveEndpoint() 메서드

public final class ExchangeHelper {
    ...
    @SuppressWarnings({"unchecked" })
    public static Endpoint
    resolveEndpoint(Exchange exchange, Object value)
        throws NoSuchEndpointException { ... }
    ...
}

resolveEndpoint() 에 대한 첫 번째 인수는 교환 인스턴스이며 두 번째 인수는 일반적으로 엔드포인트 URI 문자열입니다. 예 35.7. “파일 끝점 생성” 교환 인스턴스 교환에서 새 파일 엔드포인트를 만드는 방법을 보여줍니다.

예 35.7. 파일 끝점 생성

Endpoint file_endp = ExchangeHelper.resolveEndpoint(exchange, "file://tmp/messages/in.xml");

35.4.3. 교환 액세스 권한을 래핑

Exchange Helper 클래스는 해당 get Cryostat Property() 메서드를 교환 클래스에서 래핑하는 getMandatory CryostatProperty() 형식의 여러 정적 메서드를 제공합니다. 이들의 차이점은 원래 get CryostatProperty() 접근자가 해당 속성을 사용할 수 없는 경우 null 을 반환하고 getMandatory CryostatProperty() 는 Java 예외를 throw한다는 것입니다. 다음 래퍼 메서드는 ExchangeHelper 클래스에서 구현됩니다.

public final class ExchangeHelper {
    ...
    public static <T> T getMandatoryProperty(Exchange exchange, String propertyName, Class<T> type)
        throws NoSuchPropertyException { ... }

    public static <T> T getMandatoryHeader(Exchange exchange, String propertyName, Class<T> type)
        throws NoSuchHeaderException { ... }

    public static Object getMandatoryInBody(Exchange exchange)
        throws InvalidPayloadException { ... }

    public static <T> T getMandatoryInBody(Exchange exchange, Class<T> type)
        throws InvalidPayloadException { ... }

    public static Object getMandatoryOutBody(Exchange exchange)
        throws InvalidPayloadException { ... }

    public static <T> T getMandatoryOutBody(Exchange exchange, Class<T> type)
        throws InvalidPayloadException { ... }
    ...
}

35.4.4. 교환 패턴 테스트

다양한 교환 패턴은 In 메시지를 보유하는 것과 호환됩니다. 몇 가지 다른 교환 패턴은 외부 메시지 유지와도 호환됩니다. 교환 개체가 In 메시지 또는 Out 메시지를 유지할 수 있는지 여부를 확인하는 빠른 방법을 제공하기 위해 ExchangeHelper 클래스는 다음 메서드를 제공합니다.

public final class ExchangeHelper {
    ...
    public static boolean isInCapable(Exchange exchange) { ... }

    public static boolean isOutCapable(Exchange exchange) { ... }
    ...
}

35.4.5. In message의 MIME 콘텐츠 유형 가져오기

교환의 수신 메시지의 MIME 콘텐츠 유형을 찾으려면 ExchangeHelper.getContentType(exchange) 메서드를 호출하여 액세스할 수 있습니다. 이를 구현하기 위해 ExchangeHelper 개체는 In message의 Content-Type header Cryostat- Cryostatthis 메서드의 값을 조회하여 헤더 값을 채우기 위해 기본 구성 요소를 사용합니다.

36장. 유형 전환

초록

Apache Camel에는 메시지 본문 및 메시지 헤더를 다른 유형으로 변환하는 데 사용되는 기본 제공 유형 변환 메커니즘이 있습니다. 이 장에서는 고유한 사용자 지정 변환기 방법을 추가하여 형식 변환 메커니즘을 확장하는 방법을 설명합니다.

36.1. 유형: 아키텍처

36.1.1. 개요

이 섹션에서는 사용자 지정 형식 변환기를 작성하려는 경우 이해해야 하는 형식 변환기 메커니즘의 전반적인 아키텍처에 대해 설명합니다.This section describes the overall architecture of the type converter mechanism, which you must understand, if you want to write custom type converters. 기본 제공 유형 변환기만 사용해야 하는 경우 34장. 메시지 형식 이해 을 참조하십시오.

36.1.2. 유형 변환기 인터페이스

예 36.1. “TypeConverter 인터페이스” 모든 유형 변환기가 구현해야하는 org.apache.camel.TypeConverter 인터페이스의 정의를 보여줍니다.

예 36.1. TypeConverter 인터페이스

package org.apache.camel;

public interface TypeConverter {
    <T> T convertTo(Class<T> type, Object value);
}

36.1.3. 컨트롤러 유형 변환기

Apache Camel 유형 변환기 메커니즘은 컨트롤러/작업자 패턴을 따릅니다. 각각 제한된 수의 유형 변환과 작업자 가 수행하는 유형 변환을 집계하는 단일 컨트롤러 유형 변환기를 수행할 수 있는 작업자 유형 변환기가 많이 있습니다. 컨트롤러 유형 변환기는 작업자 유형 변환기의 프런트 엔드 역할을 합니다. 컨트롤러에서 형식 변환을 수행하도록 요청하면 적절한 작업자를 선택하고 변환 작업을 해당 작업자에 위임합니다.

형식 변환 메커니즘의 사용자에 대해 컨트롤러 유형 변환기는 변환 메커니즘에 액세스하기 위한 진입점을 제공하므로 가장 중요합니다. 시작하는 동안 Apache Camel은 컨트롤러 유형 변환기 인스턴스를 CamelContext 오브젝트에 자동으로 연결합니다. 컨트롤러 유형 변환기에 대한 참조를 얻으려면 CamelContext.getTypeConverter() 메서드를 호출합니다. 예를 들어 교환 오브젝트인 exchange 가 있는 경우 예 36.2. “컨트롤러 유형 가져오기” 에 표시된 대로 컨트롤러 유형 변환기에 대한 참조를 얻을 수 있습니다.

예 36.2. 컨트롤러 유형 가져오기

org.apache.camel.TypeConverter tc = exchange.getContext().getTypeConverter();

36.1.4. 유형 변환기 로더

컨트롤러 유형 변환기는 유형 변환기 로더 를 사용하여 작업자 유형 변환기의 레지스트리를 채웁니다. 형식 변환기 로더는 TypeConverterLoader 인터페이스를 구현하는 모든 클래스입니다. Apache Camel은 현재 하나의 종류의 컨버터 로더로 주석 유형 변환기 로더 ( AnnotationTypeConverterLoader type)를 사용합니다.

36.1.5. 유형 변환 프로세스

그림 36.1. “유형 변환 프로세스” 지정된 데이터 값, 값 , 지정된 형식으로 변환에 관련된 단계를 표시 하는 형식 변환 프로세스에 대 한 개요를 제공 합니다.Give an overview of the type conversion process, showing the steps involved in converting a given data value, value , to a specified type, toType.

그림 36.1. 유형 변환 프로세스

유형 변환 프로세스

유형 변환 메커니즘은 다음과 같이 진행됩니다.

  1. CamelContext 오브젝트에는 컨트롤러 TypeConverter 인스턴스에 대한 참조가 있습니다. 변환 프로세스의 첫 번째 단계는 CamelContext.getTypeConverter() 를 호출하여 컨트롤러 유형 변환기를 검색하는 것입니다.
  2. 유형 변환은 컨트롤러 유형 변환기에서 convertTo() 메서드를 호출하여 시작됩니다. 이 메서드는 형식 변환기에 데이터 개체 값에서 원래 형식에서 toType 인수에 의해 지정된 형식으로 변환하도록 지시합니다.This method instructs the type converter to convert the data object, value, from its original type to the type specified by the toType argument.
  3. 컨트롤러 유형 변환기는 다양한 작업자 유형 컨버터의 프런트 엔드이기 때문에 유형 매핑의 레지스트리를 확인하여 적절한 작업자 유형 변환기를 조회합니다. 형식 변환기의 레지스트리는 유형 매핑 쌍 (toType,fromType) 에 의해 키가 지정됩니다. 레지스트리에 적합한 유형 변환기가 있는 경우 컨트롤러 유형 변환기는 작업자의 convertTo() 메서드를 호출하고 결과를 반환합니다.
  4. 레지스트리에서 적합한 유형 변환기를 찾을 수 없는 경우 컨트롤러 유형 변환기는 형식 변환기 로더를 사용하여 새 형식 변환기를 로드합니다.
  5. 유형 변환기 로더는 classpath에서 사용 가능한 JAR 라이브러리를 검색하여 적합한 유형 변환기를 찾습니다. 현재 사용되는 로더 전략은 org.apache.camel.Converter 주석에서 주석이 달린 클래스를 로드하려고 하는 주석 유형 변환기 로더에 의해 구현됩니다. “TypeConverter 파일 만들기”을 참조하십시오.
  6. 형식 변환기 로더가 성공하면 새 작업자 유형 변환기가 로드되어 형식 변환기 레지스트리에 입력합니다. 그런 다음 이 형식 변환기를 사용하여 value 인수를 toType 형식으로 변환합니다.
  7. 데이터가 성공적으로 변환되면 변환된 데이터 값이 반환됩니다. 변환이 성공하지 않으면 null 이 반환됩니다.

36.2. 중복 유형 처리

중복 유형 변환기를 추가하면 발생해야 하는 작업을 구성할 수 있습니다.

TypeConverterRegistry ( 36.3절. “주석을 사용하여 유형 구현”참조)에서 다음 코드를 사용하여 작업을 Override,Ignore 또는 Fail 로 설정할 수 있습니다.

typeconverterregistry = camelContext.getTypeConverter()
// Define the behaviour if the TypeConverter already exists
typeconverterregistry.setTypeConverterExists(TypeConverterExists.Override);

이 코드의 재정의 는 요구 사항에 따라 Ignore 또는 Fail 로 교체할 수 있습니다.

36.2.1. TypeConverterExists 클래스

TypeConverterExists 클래스는 다음 명령으로 구성됩니다.

package org.apache.camel;

import javax.xml.bind.annotation.XmlEnum;

/**
 * What to do if attempting to add a duplicate type converter
 *
 * @version
 */
@XmlEnum
public enum TypeConverterExists {

    Override, Ignore, Fail

}

36.3. 주석을 사용하여 유형 구현

36.3.1. 개요

유형 변환 메커니즘은 새 작업자 유형 변환기를 추가하여 쉽게 사용자 지정할 수 있습니다. 이 섹션에서는 작업자 유형 변환기를 구현하고 Apache Camel과 통합하는 방법을 설명하므로 주석 유형 변환기 로더에 의해 자동으로 로드됩니다.

36.3.2. 형식 변환기를 구현하는 방법

사용자 지정 형식 변환기를 구현하려면 다음 단계를 수행합니다.

36.3.3. 주석이 달린 컨버터 클래스 구현

@Converter 주석을 사용하여 사용자 정의 유형 변환기 클래스를 구현할 수 있습니다. 클래스 자체와 형식 변환을 수행하기 위해 각 정적 메서드에 주석을 달아야 합니다. 각 변환기 메서드는 형식에서 정의 하는 인수를 사용 하며 선택적으로 두 번째 Exchange 인수를 사용 하며 입력할 수 있는 값을 정의 하는 비void 반환 값이 있습니다. 유형 변환기 로더는 Java 리플렉션을 사용하여 주석이 달린 방법을 찾아 형식 변환기 메커니즘에 통합합니다. 예 36.3. “Annotated Cryostat 클래스의 예” java.io.File 에서 java.io.InputStream 으로 변환하기 위한 변환기 메서드 및 byte[] 에서 String 으로 변환하는 다른 컨버터 메서드( Exchange 인수 포함)를 정의하는 주석이 있는 변환기 클래스의 예를 보여줍니다.

예 36.3. Annotated Cryostat 클래스의 예

package com.YourDomain.YourPackageName;

import org.apache.camel.Converter;

import java.io.*;

@Converter
public class IOConverter {
    private IOConverter() {
    }

    @Converter
    public static InputStream toInputStream(File file) throws FileNotFoundException {
        return new BufferedInputStream(new FileInputStream(file));
    }

    @Converter
    public static String toString(byte[] data, Exchange exchange) {
        if (exchange != null) {
            String charsetName = exchange.getProperty(Exchange.CHARSET_NAME, String.class);
            if (charsetName != null) {
                try {
                    return new String(data, charsetName);
                } catch (UnsupportedEncodingException e) {
                    LOG.warn("Can't convert the byte to String with the charset " + charsetName, e);
                }
            }
        }
        return new String(data);
    }
}

toInputStream() 메서드는 File 유형에서 InputStream 유형으로의 변환을 수행하며 toString() 메서드는 byte[] 유형에서 String 유형으로 변환을 수행해야 합니다.

참고

메서드 이름은 중요하지 않으며 원하는 대로 선택할 수 있습니다. 중요한 것은 인수 유형, 반환 유형, @Converter 주석의 존재 여부입니다.

36.3.4. TypeConverter 파일 만들기

사용자 정의 변환기에 대해 주석 유형 변환기로 구현되는 검색 메커니즘을 활성화하려면 다음 위치에서 TypeConverter 파일을 생성합니다.

META-INF/services/org/apache/camel/TypeConverter

TypeConverter 파일에는 FQN(Fully Qualified Names) 형식 변환기 클래스의 쉼표로 구분된 목록이 포함되어야 합니다. 예를 들어 형식 변환기 로더가 YourPackageName.YourClassName 패키지에 주석이 달린 컨버터 클래스를 검색하도록 하려면 TypeConverter 파일에 다음과 같은 내용이 있습니다.

com.PackageName.FooClass

검색 메커니즘을 활성화하는 다른 방법은 패키지 이름만 TypeConverter 파일에 추가하는 것입니다. 예를 들어 TypeConverter 파일에는 다음과 같은 내용이 있습니다.

com.PackageName

이로 인해 패키지 스캐너가 @Converter 태그의 패키지를 통해 스캔됩니다. FQN 방법을 사용하는 것이 더 빠르고 선호되는 방법입니다.

36.3.5. 유형 변환기 패키지

유형 변환기는 사용자 정의 유형 변환기의 컴파일된 클래스와 META-INF 디렉터리가 포함된 JAR 파일로 패키징됩니다. 이 JAR 파일을 classpath에 배치하여 Apache Camel 애플리케이션에서 사용할 수 있도록 합니다.

36.3.6. 대체 변환기 방법

@Converter 주석을 사용하여 정규식을 정의하는 것 외에도 @FallbackConverter 주석을 사용하여 대체 변환기 메서드를 선택적으로 정의할 수 있습니다. 컨트롤러 유형 변환기가 유형 레지스트리에서 일반 컨버터 메서드를 찾지 못하는 경우에만 대체 변환기 방법이 시도됩니다.

일반 변환기 메서드와 대체 변환기 메서드의 근본적인 차이점은 일반 변환기가 특정 유형 쌍(예: 바이트[] 에서 문자열까지) 간의 변환을 수행하도록 정의되지만 대체 변환기는 모든 유형의 쌍 간에 변환을 수행할 수 있다는 것입니다. 대체 변환기 메서드의 본문에 있는 코드는 수행할 수 있는 변환을 파악합니다. 런타임에 일반 변환기에서 변환을 수행할 수 없는 경우, 컨트롤러 유형 변환기는 변환을 수행할 수 있는 옵션을 찾을 때까지 사용 가능한 모든 대체 변환기를 통해 반복합니다.

대체 변환기의 메서드 서명에는 다음 양식 중 하나가 있을 수 있습니다.

// 1. Non-generic form of signature
@FallbackConverter
public static Object MethodName(
    Class type,
    Exchange exchange,
    Object value,
    TypeConverterRegistry registry
)

// 2. Templating form of signature
@FallbackConverter
public static <T> T MethodName(
    Class<T> type,
    Exchange exchange,
    Object value,
    TypeConverterRegistry registry
)

여기서 MethodName 은 대체 변환기에 대한 임의의 메서드 이름입니다.

예를 들어 다음 코드 추출(File 구성 요소 구현에서 가져온)은 GenericFile 개체의 본문을 변환하여 유형 변환기 레지스트리에서 이미 사용 가능한 유형 변환기를 악용할 수 있는 대체 변환기를 보여줍니다.

package org.apache.camel.component.file;

import org.apache.camel.Converter;
import org.apache.camel.FallbackConverter;
import org.apache.camel.Exchange;
import org.apache.camel.TypeConverter;
import org.apache.camel.spi.TypeConverterRegistry;

@Converter
public final class GenericFileConverter {

    private GenericFileConverter() {
        // Helper Class
    }

    @FallbackConverter
    public static <T> T convertTo(Class<T> type, Exchange exchange, Object value, TypeConverterRegistry registry) {
        // use a fallback type converter so we can convert the embedded body if the value is GenericFile
        if (GenericFile.class.isAssignableFrom(value.getClass())) {
            GenericFile file = (GenericFile) value;
            Class from = file.getBody().getClass();
            TypeConverter tc = registry.lookup(type, from);
            if (tc != null) {
                Object body = file.getBody();
                return tc.convertTo(type, exchange, body);
            }
        }

        return null;
    }
    ...
}

36.4. 직접 유형 구현

36.4.1. 개요

일반적으로 유형 변환기를 구현하는 권장 방법은 이전 섹션 36.3절. “주석을 사용하여 유형 구현” 에 설명된 대로 주석이 달린 클래스를 사용하는 것입니다. 그러나 형식 변환기의 등록을 완전히 제어하려면 사용자 정의 작업자 유형 변환기를 구현하고 여기에 설명된 대로 형식 변환기 레지스트리에 직접 추가할 수 있습니다.

36.4.2. TypeConverter 인터페이스 구현

고유한 형식 변환기 클래스를 구현하려면 TypeConverter 인터페이스를 구현하는 클래스를 정의합니다. 예를 들어 다음 MyOrder TypeConverter 클래스는 정수 값을 MyOrder 개체로 변환합니다. 여기서 정수 값은 MyOrder 개체의 순서 ID를 초기화하는 데 사용됩니다.

import org.apache.camel.TypeConverter

private class MyOrderTypeConverter implements TypeConverter {

    public <T> T convertTo(Class<T> type, Object value) {
        // converter from value to the MyOrder bean
        MyOrder order = new MyOrder();
        order.setId(Integer.parseInt(value.toString()));
        return (T) order;
    }

    public <T> T convertTo(Class<T> type, Exchange exchange, Object value) {
        // this method with the Exchange parameter will be preferd by Camel to invoke
        // this allows you to fetch information from the exchange during convertions
        // such as an encoding parameter or the likes
        return convertTo(type, value);
    }

    public <T> T mandatoryConvertTo(Class<T> type, Object value) {
        return convertTo(type, value);
    }

    public <T> T mandatoryConvertTo(Class<T> type, Exchange exchange, Object value) {
        return convertTo(type, value);
    }
}

36.4.3. 레지스트리에 유형 변환기 추가

다음과 같은 코드를 사용하여 형식 변환기 레지스트리에 사용자 정의 유형 변환기를 직접 추가할 수 있습니다.

// Add the custom type converter to the type converter registry
context.getTypeConverterRegistry().addTypeConverter(MyOrder.class, String.class, new MyOrderTypeConverter());

여기서 context 는 현재 org.apache.camel.CamelContext 인스턴스입니다. addTypeConverter() 메서드는 String.class 에서 MyOrder.class 로 특정 형식 변환에 대해 MyOrderTypeConverter 클래스를 등록합니다.

META-INF 파일을 사용하지 않고도 Camel 애플리케이션에 사용자 정의 유형 변환기를 추가할 수 있습니다. Spring 또는 블루프린트 를 사용하는 경우 <bean>을 선언하면 됩니다. CamelContext에서 빈을 자동으로 검색하고 변환기를 추가합니다.

<bean id="myOrderTypeConverters" class="..."/>
 <camelContext>
   ...
</camelContext>

클래스가 더 많은 경우 여러 <bean>s를 선언할 수 있습니다.

37장. 생산자 및 소비자 템플릿

초록

Apache Camel의 생산자 및 소비자 템플릿은 Spring 컨테이너 API의 기능 후에 모델링되며, 여기서 리소스에 대한 액세스는 템플릿 이라는 간소화되고 사용하기 쉬운 API를 통해 제공됩니다. Apache Camel의 경우 생산자 템플릿과 소비자 템플릿은 생산자 끝점 및 소비자 끝점으로 메시지를 보내고 메시지를 수신하기 위한 단순화된 인터페이스를 제공합니다.

37.1. Producer 템플릿 사용

37.1.1. Producer 템플릿 소개

37.1.1.1. 개요

생산자 템플릿은 생산자 엔드포인트를 호출하는 다양한 방법을 지원합니다. 요청 메시지( Exchange 개체, 메시지 본문, 메시지 본문 등)에 대해 다양한 형식을 지원하는 메서드가 있으며 단일 헤더 설정이 있는 메시지 본문으로, 동기 및 비동기 호출 스타일을 모두 지원하는 방법이 있습니다. 전반적으로 생산자 템플릿 메서드를 다음 범주로 그룹화할 수 있습니다.

또는 37.2절. “Fluent Producer 템플릿 사용” 을 참조하십시오.

37.1.1.2. 동기 호출

끝점을 동기적으로 호출하는 방법에는 sendSuffix() 및 요청Suffix () 의 이름이 있습니다. 예를 들어 기본 메시지 교환 패턴(MEP) 또는 명시적으로 지정된 MEP를 사용하여 끝점을 호출하는 방법은 send(), sendBody()sendBodyAndHeader() (이 메서드 각각 교환 오브젝트, 메시지 본문 또는 메시지 본문 및 헤더 값을 전송하는)라는 이름이 지정됩니다. MEP를 InOut (request/reply semantics)으로 강제 적용하려면 request(), requestBody()requestBodyAndHeader() 메서드를 대신 호출할 수 있습니다.

다음 예제에서는 ProducerTemplate 인스턴스를 생성하고 이를 사용하여 메시지 본문을 activemq:MyQueue 엔드포인트에 전송하는 방법을 보여줍니다. 이 예제에서는 sendBodyAndHeader() 를 사용하여 메시지 본문과 헤더 값을 보내는 방법도 보여줍니다.

import org.apache.camel.ProducerTemplate
import org.apache.camel.impl.DefaultProducerTemplate
...
ProducerTemplate template = context.createProducerTemplate();

// Send to a specific queue
template.sendBody("activemq:MyQueue", "<hello>world!</hello>");

// Send with a body and header
template.sendBodyAndHeader(
    "activemq:MyQueue",
    "<hello>world!</hello>",
    "CustomerRating", "Gold" );

37.1.1.3. 프로세서와 동기 호출

동기 호출의 특수한 경우는 Exchange 인수 대신 send() 메서드에 Processor 인수를 제공하는 것입니다. 이 경우 생산자 템플릿은 지정된 엔드포인트에서 교환 인스턴스를 생성하도록 암시적으로 요청합니다(일반적으로 InOnly MEP가 기본적으로 있음). 이 기본 교환은 프로세서로 전달되어 교환 오브젝트의 콘텐츠를 초기화합니다.

다음 예제에서는 MyProcessor 프로세서에서 초기화한 교환을 activemq:MyQueue 엔드포인트로 보내는 방법을 보여줍니다.

import org.apache.camel.ProducerTemplate
import org.apache.camel.impl.DefaultProducerTemplate
...
ProducerTemplate template = context.createProducerTemplate();

// Send to a specific queue, using a processor to initialize
template.send("activemq:MyQueue", new MyProcessor());

다음 예와 같이 MyProcessor 클래스가 구현됩니다. 메시지 본문(여기에 표시됨)을 설정하는 것 외에도 메시지 헤더를 초기화하고 속성을 교환할 수 있습니다.

import org.apache.camel.Processor;
import org.apache.camel.Exchange;
...
public class MyProcessor implements Processor {
    public MyProcessor() { }

    public void process(Exchange ex) {
        ex.getIn().setBody("<hello>world!</hello>");
    }
}

37.1.1.4. 비동기 호출

끝점을 비동기적으로 호출하는 메서드의 이름은 asyncSendSuffix()asyncRequestSuffix() 형식의 이름이 있습니다. 예를 들어 기본 메시지 교환 패턴(MEP) 또는 명시적으로 지정된 MEP를 사용하여 끝점을 호출하는 방법은 asyncSend()asyncSendBody() 라는 이름이 지정됩니다(이러한 메서드는 각각 교환 개체 또는 메시지 본문을 보내는 경우). MEP를 InOut (request/reply semantics)으로 강제 적용하려면 asyncRequestBody(), asyncRequestBodyAndHeader()asyncRequestBodyAndHeaders() 메서드를 대신 호출할 수 있습니다.

다음 예제에서는 교환을 비동기적으로 direct:start 끝점으로 보내는 방법을 보여줍니다. asyncSend() 메서드는 나중에 호출 결과를 검색하는 데 사용되는 java.util.concurrent.Future 개체를 반환합니다.

import java.util.concurrent.Future;

import org.apache.camel.Exchange;
import org.apache.camel.impl.DefaultExchange;
...
Exchange exchange = new DefaultExchange(context);
exchange.getIn().setBody("Hello");

Future<Exchange> future = template.asyncSend("direct:start", exchange);

// You can do other things, whilst waiting for the invocation to complete
...
// Now, retrieve the resulting exchange from the Future
Exchange result = future.get();

생산자 템플릿은 메시지 본문을 비동기식으로 보내는 메서드도 제공합니다(예: asyncSendBody() 또는 asyncRequestBody()). 이 경우 future 개체에서 반환된 메시지 본문을 추출하기 위해 다음 도우미 메서드 중 하나를 사용할 수 있습니다.In this case, you can use one of the following helper methods to extract the returned message body from the Future object:

<T> T extractFutureBody(Future future, Class<T> type);
<T> T extractFutureBody(Future future, long timeout, TimeUnit unit, Class<T> type) throws TimeoutException;

extractFutureBody() 메서드의 첫 번째 버전은 호출이 완료되고 응답 메시지를 사용할 수 있을 때까지 차단됩니다. extractFutureBody() 메서드의 두 번째 버전을 사용하면 시간 초과를 지정할 수 있습니다. 두 메서드 모두 반환된 메시지 본문을 기본 제공 형식 변환기를 사용하여 지정된 형식으로 캐스팅하는 형식 인수입니다.Both methods have a type argument, type , which casts the returned message body to the specified type using a built-in type converter.

다음 예제에서는 asyncRequestBody() 메서드를 사용하여 메시지 본문을 direct:start 엔드포인트에 보내는 방법을 보여줍니다. 그런 다음 차단 extractFutureBody() 메서드는 Future 개체에서 응답 메시지 본문을 검색하는 데 사용됩니다.

Future<Object> future = template.asyncRequestBody("direct:start", "Hello");

// You can do other things, whilst waiting for the invocation to complete
...
// Now, retrieve the reply message body as a String type
String result = template.extractFutureBody(future, String.class);

37.1.1.5. 콜백을 사용한 비동기 호출

앞의 비동기 예제에서 요청 메시지는 하위 스레드에서 디스패치되는 반면, 기본 스레드에서 응답을 검색하고 처리합니다. 또한 프로듀서 템플릿은 옵션을 제공하지만, asyncCallback(), asyncCallbackSendBody() 또는 asyncCallbackRequestBody() 메서드 중 하나를 사용하여 하위 스레드의 응답 처리도 제공합니다. 이 경우 응답 메시지가 도달하는 즉시 하위 스레드에서 자동으로 호출되는 org.apache.camel.impl.SynchronizationAdapter 유형의 콜백 오브젝트를 제공합니다.

동기화 콜백 인터페이스는 다음과 같이 정의됩니다.

package org.apache.camel.spi;

import org.apache.camel.Exchange;

public interface Synchronization {
    void onComplete(Exchange exchange);
    void onFailure(Exchange exchange);
}

일반적인 응답을 수신할 때 onComplete() 메서드가 호출되고 오류 메시지 응답을 수신할 때 onFailure() 메서드가 호출됩니다. 이러한 메서드 중 하나만 다시 호출되므로 모든 유형의 응답을 처리하려면 두 메서드를 모두 재정의해야 합니다.

다음 예제에서는 SynchronizationAdapter 콜백 개체를 통해 응답 메시지가 하위 스레드에서 처리되는 direct:start 엔드포인트로 교환을 보내는 방법을 보여줍니다.

import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

import org.apache.camel.Exchange;
import org.apache.camel.impl.DefaultExchange;
import org.apache.camel.impl.SynchronizationAdapter;
...
Exchange exchange = context.getEndpoint("direct:start").createExchange();
exchange.getIn().setBody("Hello");

Future<Exchange> future = template.asyncCallback("direct:start", exchange, new SynchronizationAdapter() {
    @Override
    public void onComplete(Exchange exchange) {
        assertEquals("Hello World", exchange.getIn().getBody());
    }
});

여기서 Synchronization Adapter 클래스는 동기화 인터페이스의 기본 구현이며, 이를 재정의하여 onComplete()onFailure() 콜백 메서드에 대한 자체 정의를 제공할 수 있습니다.

asyncCallback() 메서드도 Future 개체가 반환되므로 기본 스레드에서 응답에 액세스하는 옵션이 있습니다. 예를 들면 다음과 같습니다.

// Retrieve the reply from the main thread, specifying a timeout
Exchange reply = future.get(10, TimeUnit.SECONDS);

37.1.2. 동기화 전송

37.1.2.1. 개요

동기 전송 방법은 메서드 호출이 완료되고 응답(있는 경우)이 수신될 때까지 현재 스레드가 차단되는 생산자 엔드포인트를 호출하는 데 사용할 수 있는 메서드 컬렉션입니다. 이러한 방법은 모든 종류의 메시지 교환 프로토콜과 호환됩니다.

37.1.2.2. 교환 보내기

basic send() 메서드는 교환의 MEP(메시지 교환 패턴)를 사용하여 교환 개체의 내용을 엔드포인트로 전송하는 범용 메서드입니다. 반환 값은 생산자 엔드포인트에서 처리한 후 얻을 수 있는 교환입니다(MEP에 따라 Out 메시지가 포함될 수 있음).

다음 방법 중 하나로 대상 엔드포인트를 지정하거나 엔드포인트 URI로 또는 Endpoint 개체로 지정할 수 있는 교환을 보내는 send() 메서드의 세 가지 유형이 있습니다.

Exchange send(Exchange exchange);
Exchange send(String endpointUri, Exchange exchange);
Exchange send(Endpoint endpoint, Exchange exchange);

37.1.2.3. 프로세서에 의해 채워진 교환 보내기

일반적인 send() 메서드의 간단한 변형은 교환 오브젝트를 명시적으로 제공하는 대신 프로세서를 사용하여 기본 교환을 채우는 것입니다(자세한 내용은 “프로세서와 동기 호출” 참조).

프로세서로 채워진 교환을 보내기 위한 send() 메서드를 사용하면 기본 끝점으로, 엔드포인트 URI로 또는 Endpoint 오브젝트로 다음과 같은 방법 중 하나로 대상 끝점을 지정할 수 있습니다. 또한 기본값을 수락하는 대신 패턴 인수를 제공하여 교환의 MEP를 선택적으로 지정할 수 있습니다.

Exchange send(Processor processor);
Exchange send(String endpointUri, Processor processor);
Exchange send(Endpoint endpoint, Processor processor);
Exchange send(
    String endpointUri,
    ExchangePattern pattern,
    Processor processor
);
Exchange send(
    Endpoint endpoint,
    ExchangePattern pattern,
    Processor processor
);

37.1.2.4. 메시지 본문 전송

보내려는 메시지 본문의 콘텐츠에만 관련된 경우 sendBody() 메서드를 사용하여 메시지 본문을 인수로 제공하고 생산자 템플릿에서 본문을 기본 교환 오브젝트에 삽입하도록 할 수 있습니다.

sendBody() 메서드를 사용하면 기본 엔드포인트, 엔드포인트 URI 또는 끝점 오브젝트로 다음과 같은 방법 중 하나로 대상 끝점을 지정할 수 있습니다. 또한 기본값을 수락하는 대신 패턴 인수를 제공하여 교환의 MEP를 선택적으로 지정할 수 있습니다. 패턴 인수 반환 void없는 메서드(요청이 어떤 경우에는 회신을 발생시킬 수 있음)와 패턴 인수가 있는 메서드는 Out 메시지의 본문 또는 In 메시지 본문을 반환합니다.

void sendBody(Object body);
void sendBody(String endpointUri, Object body);
void sendBody(Endpoint endpoint, Object body);
Object sendBody(
    String endpointUri,
    ExchangePattern pattern,
    Object body
);
Object sendBody(
    Endpoint endpoint,
    ExchangePattern pattern,
    Object body
);

37.1.2.5. 메시지 본문 및 헤더 전송

테스트 목적을 위해 단일 헤더 설정의 효과를 시도하는 것이 중요하며 sendBodyAndHeader() 메서드는 이러한 종류의 헤더 테스트에 유용합니다. 메시지 본문 및 헤더 설정을 sendBodyAndHeader() 에 인수로 제공하고 생산자 템플릿에서 본문 및 헤더 설정을 기본 교환 오브젝트에 삽입하도록 합니다.

sendBodyAndHeader() 메서드를 사용하면 다음과 같은 방법 중 하나로 대상 끝점을 지정할 수 있습니다. 기본 끝점으로, 엔드포인트 URI로 또는 끝점 오브젝트로 지정할 수 있습니다. 또한 기본값을 수락하는 대신 패턴 인수를 제공하여 교환의 MEP를 선택적으로 지정할 수 있습니다. 패턴 인수 반환 void없는 메서드(요청이 어떤 경우에는 회신을 발생시킬 수 있음)와 패턴 인수가 있는 메서드는 Out 메시지의 본문 또는 In 메시지 본문을 반환합니다.

void sendBodyAndHeader(
    Object body,
    String header,
    Object headerValue
);
void sendBodyAndHeader(
    String endpointUri,
    Object body,
    String header,
    Object headerValue
);
void sendBodyAndHeader(
    Endpoint endpoint,
    Object body,
    String header,
    Object headerValue
);
Object sendBodyAndHeader(
    String endpointUri,
    ExchangePattern pattern,
    Object body,
    String header,
    Object headerValue
);
Object sendBodyAndHeader(
    Endpoint endpoint,
    ExchangePattern pattern,
    Object body,
    String header,
    Object headerValue
);

sendBodyAndHeaders() 메서드는 단일 헤더 설정만 제공하는 대신 헤더 설정의 전체 해시 맵을 지정할 수 있다는 점을 제외하고 sendBodyAndHeader() 메서드와 유사합니다.

void sendBodyAndHeaders(
    Object body,
    Map<String, Object> headers
);
void sendBodyAndHeaders(
    String endpointUri,
    Object body,
    Map<String, Object> headers
);
void sendBodyAndHeaders(
    Endpoint endpoint,
    Object body,
    Map<String, Object> headers
);
Object sendBodyAndHeaders(
    String endpointUri,
    ExchangePattern pattern,
    Object body,
    Map<String, Object> headers
);
Object sendBodyAndHeaders(
    Endpoint endpoint,
    ExchangePattern pattern,
    Object body,
    Map<String, Object> headers
);

37.1.2.6. 메시지 본문을 보내고 속성을 교환

sendBodyAndProperty() 메서드를 사용하여 단일 교환 속성을 설정하는 효과를 시도할 수 있습니다. 메시지 본문 및 속성 설정을 sendBodyAndProperty() 에 인수로 제공하고 생산자 템플릿에서 본문 삽입을 처리하고 속성을 기본 교환 오브젝트에 교환하도록 합니다.

sendBodyAndProperty() 메서드를 사용하면 다음과 같은 방법 중 하나로 대상 끝점을 지정할 수 있습니다. 기본 끝점으로, 엔드포인트 URI로 또는 끝점 개체로 지정할 수 있습니다. 또한 기본값을 수락하는 대신 패턴 인수를 제공하여 교환의 MEP를 선택적으로 지정할 수 있습니다. 패턴 인수 반환 void없는 메서드(요청이 어떤 경우에는 회신을 발생시킬 수 있음)와 패턴 인수가 있는 메서드는 Out 메시지의 본문 또는 In 메시지 본문을 반환합니다.

void sendBodyAndProperty(
    Object body,
    String property,
    Object propertyValue
);
void sendBodyAndProperty(
    String endpointUri,
    Object body,
    String property,
    Object propertyValue
);
void sendBodyAndProperty(
    Endpoint endpoint,
    Object body,
    String property,
    Object propertyValue
);
Object sendBodyAndProperty(
    String endpoint,
    ExchangePattern pattern,
    Object body,
    String property,
    Object propertyValue
);
Object sendBodyAndProperty(
    Endpoint endpoint,
    ExchangePattern pattern,
    Object body,
    String property,
    Object propertyValue
);

37.1.3. InOut 패턴의 동기 요청

37.1.3.1. 개요

동기식 요청 방법은 메시지 교환 패턴이 InOut (요청/응답 의미)으로 강제된다는 점을 제외하고 동기 전송 방법과 유사합니다. 따라서 생산자 끝점에서 응답을 수신할 것으로 예상되는 경우 일반적으로 동기 요청 방법을 사용하는 것이 편리합니다.

37.1.3.2. 프로세서에 의해 채워진 교환 요청

기본 request() 메서드는 프로세서를 사용하여 기본 교환을 채우고 메시지 교환 패턴을 InOut 로 강제 적용하는 일반적인 용도의 메서드입니다. 반환 값은 생산자 엔드포인트에서 처리한 후 얻을 수 있는 교환으로, Out 메시지에 응답 메시지가 포함됩니다.

프로세서에 의해 채워진 교환을 보내기 위한 request() 메서드를 사용하면 다음과 같은 방법 중 하나로 대상 엔드포인트를 지정할 수 있습니다. 엔드포인트 URI로 또는 끝점 개체로 지정할 수 있습니다.

Exchange request(String endpointUri, Processor processor);
Exchange request(Endpoint endpoint, Processor processor);

37.1.3.3. 메시지 본문 요청

요청의 메시지 본문 내용 및 응답에 대해서만 관심이 있는 경우 requestBody() 메서드를 사용하여 요청 메시지 본문을 인수로 제공하고 생산자 템플릿에서 본문을 기본 교환 오브젝트에 삽입하도록 할 수 있습니다.

requestBody() 메서드를 사용하면 기본 엔드포인트, 엔드포인트 URI 또는 끝점 오브젝트로 다음과 같은 방법 중 하나로 대상 끝점을 지정할 수 있습니다. 반환 값은 응답 메시지 본문(Out message body)의 본문이며, 이는 일반 오브젝트로 반환되거나 내장형 유형인 T 로 변환될 수 있습니다( 34.3절. “붙박임 유형”참조).

Object requestBody(Object body);
<T> T requestBody(Object body, Class<T> type);
Object requestBody(
    String endpointUri,
    Object body
);
<T> T requestBody(
    String endpointUri,
    Object body,
    Class<T> type
);
Object requestBody(
    Endpoint endpoint,
    Object body
);
<T> T requestBody(
    Endpoint endpoint,
    Object body,
    Class<T> type
);

37.1.3.4. 메시지 본문 및 헤더 요청

requestBodyAndHeader() 메서드를 사용하여 단일 헤더 값을 설정하는 효과를 시도할 수 있습니다. 메시지 본문 및 헤더 설정을 requestBodyAndHeader() 에 인수로 제공하고 생산자 템플릿에서 본문 삽입을 처리하고 속성을 기본 교환 오브젝트에 교환하도록 합니다.

requestBodyAndHeader() 메서드를 사용하면 끝점 URI로 또는 끝점 오브젝트로 다음과 같은 방법 중 하나로 대상 끝점을 지정할 수 있습니다. 반환 값은 응답 메시지 본문(Out message body)의 본문이며, 이는 일반 오브젝트로 반환되거나 내장형 유형인 T 로 변환될 수 있습니다( 34.3절. “붙박임 유형”참조).

Object requestBodyAndHeader(
    String endpointUri,
    Object body,
    String header,
    Object headerValue
);
<T> T requestBodyAndHeader(
    String endpointUri,
    Object body,
    String header,
    Object headerValue,
    Class<T> type
);
Object requestBodyAndHeader(
    Endpoint endpoint,
    Object body,
    String header,
    Object headerValue
);
<T> T requestBodyAndHeader(
    Endpoint endpoint,
    Object body,
    String header,
    Object headerValue,
    Class<T> type
);

requestBodyAndHeaders() 메서드는 단일 헤더 설정만 제공하는 대신 헤더 설정에 대한 전체 해시 맵을 지정할 수 있다는 점을 제외하고 requestBodyAndHeader() 메서드와 유사합니다.

Object requestBodyAndHeaders(
    String endpointUri,
    Object body,
    Map<String, Object> headers
);
<T> T requestBodyAndHeaders(
    String endpointUri,
    Object body,
    Map<String, Object> headers,
    Class<T> type
);
Object requestBodyAndHeaders(
    Endpoint endpoint,
    Object body,
    Map<String, Object> headers
);
<T> T requestBodyAndHeaders(
    Endpoint endpoint,
    Object body,
    Map<String, Object> headers,
    Class<T> type
);

37.1.4. 비동기 전송

37.1.4.1. 개요

생산자 템플릿은 생산자 엔드포인트를 비동기적으로 호출하는 다양한 메서드를 제공하므로 기본 스레드가 호출이 완료될 때까지 기다리는 동안 차단되지 않고 나중에 응답 메시지를 검색할 수 있습니다. 이 섹션에 설명된 비동기 전송 방법은 모든 종류의 메시지 교환 프로토콜과 호환됩니다.

37.1.4.2. 교환 보내기

기본 asyncSend() 메서드는 Exchange 인수를 사용하여 지정된 교환의 메시지 교환 패턴(MEP)을 사용하여 비동기식으로 엔드포인트를 호출합니다. 반환 값은 java.util.concurrent.Future 오브젝트로, 나중에 Future 오브젝트에서 반환 값을 얻는 방법에 대한 자세한 내용은 “비동기 호출” 에서 응답 메시지를 수집하는 데 사용할 수 있는 티켓입니다.

다음 asyncSend() 메서드를 사용하면 끝점 URI로 또는 끝점 개체로 다음과 같은 방법 중 하나로 대상 끝점을 지정할 수 있습니다.

Future<Exchange> asyncSend(String endpointUri, Exchange exchange);
Future<Exchange> asyncSend(Endpoint endpoint, Exchange exchange);

37.1.4.3. 프로세서에 의해 채워진 교환 보내기

일반적인 비동기Send() 메서드의 간단한 변형은 교환 개체를 명시적으로 제공하는 대신 프로세서를 사용하여 기본 교환을 채우는 것입니다.

다음 asyncSend() 메서드를 사용하면 끝점 URI로 또는 끝점 개체로 다음과 같은 방법 중 하나로 대상 끝점을 지정할 수 있습니다.

Future<Exchange> asyncSend(String endpointUri, Processor processor);
Future<Exchange> asyncSend(Endpoint endpoint, Processor processor);

37.1.4.4. 메시지 본문 전송

보내려는 메시지 본문의 내용만 관련된 경우 asyncSendBody() 메서드를 사용하여 메시지 본문을 비동기적으로 전송하고 생산자 템플릿에서 본문을 기본 교환 오브젝트에 삽입하도록 할 수 있습니다.

asyncSendBody() 메서드를 사용하면 끝점 URI로 또는 끝점 개체로 다음과 같은 방법 중 하나로 대상 끝점을 지정할 수 있습니다.

Future<Object> asyncSendBody(String endpointUri, Object body);
Future<Object> asyncSendBody(Endpoint endpoint, Object body);

37.1.5. InOut 패턴을 사용한 비동기 요청

37.1.5.1. 개요

비동기 요청 메서드는 메시지 교환 패턴을 InOut (요청/반복)으로 강제 적용하는 것을 제외하고 비동기 send 메서드와 유사합니다. 따라서 생산자 끝점에서 응답을 수신하려는 경우 일반적으로 비동기 요청 방법을 사용하는 것이 편리합니다.

37.1.5.2. 메시지 본문 요청

요청의 메시지 본문 내용 및 응답에 대해서만 관심이 있는 경우 requestBody() 메서드를 사용하여 요청 메시지 본문을 인수로 제공하고 생산자 템플릿에서 본문을 기본 교환 오브젝트에 삽입하도록 할 수 있습니다.

asyncRequestBody() 메서드를 사용하면 끝점 URI로 또는 끝점 개체로 다음과 같은 방법 중 하나로 대상 끝점을 지정할 수 있습니다. Future 오브젝트에서 검색할 수 있는 반환 값은 응답 메시지 본문(Out message body)의 본문입니다. 이 본문은 일반 Object 로 반환하거나 내장형 유형 변환기를 사용하여 T 로 변환할 수 있습니다( “비동기 호출”참조).

Future<Object> asyncRequestBody(
    String endpointUri,
    Object body
);
<T> Future<T> asyncRequestBody(
    String endpointUri,
    Object body,
    Class<T> type
);
Future<Object> asyncRequestBody(
    Endpoint endpoint,
    Object body
);
<T> Future<T> asyncRequestBody(
    Endpoint endpoint,
    Object body,
    Class<T> type
);

37.1.5.3. 메시지 본문 및 헤더 요청

asyncRequestBodyAndHeader() 메서드를 사용하여 단일 헤더 값을 설정하는 효과를 시도할 수 있습니다. 메시지 본문 및 헤더 설정을 asyncRequestBodyAndHeader() 에 인수로 제공하고 생산자 템플릿에서 본문을 삽입하고 속성을 기본 교환 오브젝트에 교환하도록 합니다.

asyncRequestBodyAndHeader() 메서드를 사용하면 끝점 URI로 또는 끝점 개체로 다음과 같은 방법 중 하나로 대상 끝점을 지정할 수 있습니다. Future 오브젝트에서 검색할 수 있는 반환 값은 응답 메시지 본문(Out message body)의 본문입니다. 이 본문은 일반 Object 로 반환하거나 내장형 유형 변환기를 사용하여 T 로 변환할 수 있습니다( “비동기 호출”참조).

Future<Object> asyncRequestBodyAndHeader(
    String endpointUri,
    Object body,
    String header,
    Object headerValue
);
<T> Future<T> asyncRequestBodyAndHeader(
    String endpointUri,
    Object body,
    String header,
    Object headerValue,
    Class<T> type
);
Future<Object> asyncRequestBodyAndHeader(
    Endpoint endpoint,
    Object body,
    String header,
    Object headerValue
);
<T> Future<T> asyncRequestBodyAndHeader(
    Endpoint endpoint,
    Object body,
    String header,
    Object headerValue,
    Class<T> type
);

asyncRequestBodyAndHeaders() 메서드는 asyncRequestBodyAndHeader() 메서드와 유사합니다. 단, 단일 헤더 설정만 제공하는 대신 이러한 메서드를 사용하면 헤더 설정에 대한 전체 해시 맵을 지정할 수 있습니다.

Future<Object> asyncRequestBodyAndHeaders(
    String endpointUri,
    Object body,
    Map<String, Object> headers
);
<T> Future<T> asyncRequestBodyAndHeaders(
    String endpointUri,
    Object body,
    Map<String, Object> headers,
    Class<T> type
);
Future<Object> asyncRequestBodyAndHeaders(
    Endpoint endpoint,
    Object body,
    Map<String, Object> headers
);
<T> Future<T> asyncRequestBodyAndHeaders(
    Endpoint endpoint,
    Object body,
    Map<String, Object> headers,
    Class<T> type
);

37.1.6. 콜백을 사용하여 비동기 전송

37.1.6.1. 개요

생산자 템플릿은 생산자 엔드포인트를 호출하는 데 사용되는 동일한 하위 스레드에서 응답 메시지를 처리하는 옵션도 제공합니다. 이 경우 응답 메시지가 수신되는 즉시 하위 스레드에서 자동으로 호출되는 콜백 오브젝트를 제공합니다. 즉, 콜백 메서드를 사용한 비동기 전송을 사용하면 주 스레드에서 호출을 시작한 다음 생산자 끝점의 모든 관련 처리의 모든 관련 처리를 가질 수 있으며 응답을 대기하고 응답을 처리하고 하위 스레드에서 비동기적으로 발생합니다.In other words, the asynchronous send with callback methods enable you to initiate an invocation in your main thread and then have all of the associated processing Cryostat- Cryostatinvocation of the producer endpoint, waiting for a reply and processing the reply Cryostat- Cryostatoccur asynchronously in a subthread.

37.1.6.2. 교환 보내기

기본 asyncCallback() 메서드는 Exchange 인수를 사용하여 지정된 교환의 메시지 교환 패턴(MEP)을 사용하여 비동기식으로 엔드포인트를 호출합니다. 이 방법은 교환을 위한 asyncSend() 방법과 유사하지만 추가 org.apache.camel.spi.Synchronization 인수가 필요합니다. 이 인수는 onComplete()onFailure() 의 두 가지 방법이 있는 콜백 인터페이스입니다. 동기화 콜백을 사용하는 방법에 대한 자세한 내용은 “콜백을 사용한 비동기 호출” 을 참조하십시오.

다음 asyncCallback() 메서드를 사용하면 끝점 URI로 또는 끝점 개체로 다음과 같은 방법 중 하나로 대상 끝점을 지정할 수 있습니다.

Future<Exchange> asyncCallback(
    String endpointUri,
    Exchange exchange,
    Synchronization onCompletion
);
Future<Exchange> asyncCallback(
    Endpoint endpoint,
    Exchange exchange,
    Synchronization onCompletion
);

37.1.6.3. 프로세서에 의해 채워진 교환 보내기

프로세서의 asyncCallback() 메서드는 프로세서를 호출하여 기본 교환을 채우고 메시지 교환 패턴을 InOut 으로 강제 적용합니다(즉, 호출이 요청/반복을 따르도록).

다음 asyncCallback() 메서드를 사용하면 끝점 URI로 또는 끝점 개체로 다음과 같은 방법 중 하나로 대상 끝점을 지정할 수 있습니다.

Future<Exchange> asyncCallback(
    String endpointUri,
    Processor processor,
    Synchronization onCompletion
);
Future<Exchange> asyncCallback(
    Endpoint endpoint,
    Processor processor,
    Synchronization onCompletion
);

37.1.6.4. 메시지 본문 전송

보내려는 메시지 본문의 콘텐츠에만 관련된 경우 asyncCallbackSendBody() 메서드를 사용하여 메시지 본문을 비동기적으로 전송하고 생산자 템플릿에서 본문을 기본 교환 오브젝트에 삽입하도록 할 수 있습니다.

asyncCallbackSendBody() 메서드를 사용하면 끝점 URI로 또는 끝점 개체로 다음과 같은 방법 중 하나로 대상 끝점을 지정할 수 있습니다.

Future<Object> asyncCallbackSendBody(
    String endpointUri,
    Object body,
    Synchronization onCompletion
);
Future<Object> asyncCallbackSendBody(
    Endpoint endpoint,
    Object body,
    Synchronization onCompletion
);

37.1.6.5. 메시지 본문 요청

요청에 있는 메시지 본문의 내용 및 응답에 대해서만 관심이 있는 경우 asyncCallbackRequestBody() 메서드를 사용하여 요청 메시지 본문을 인수로 제공하고 생산자 템플릿에서 본문을 기본 교환 오브젝트에 삽입하도록 할 수 있습니다.

asyncCallbackRequestBody() 메서드를 사용하면 끝점 URI 또는 끝점 개체로 다음과 같은 방법 중 하나로 대상 끝점을 지정할 수 있습니다.

Future<Object> asyncCallbackRequestBody(
    String endpointUri,
    Object body,
    Synchronization onCompletion
);
Future<Object> asyncCallbackRequestBody(
    Endpoint endpoint,
    Object body,
    Synchronization onCompletion
);

37.2. Fluent Producer 템플릿 사용

37.2.1. Camel 2.18로 사용 가능

FluentProducerTemplate 인터페이스는 생산자를 구축하기 위한 fluent 구문을 제공합니다. DefaultFluentProducerTemplate 클래스는 FluentProducerTemplate 을 구현합니다.

다음 예제에서는 DefaultFluentProducerTemplate 오브젝트를 사용하여 헤더와 본문을 설정합니다.

Integer result = DefaultFluentProducerTemplate.on(context)
    .withHeader("key-1", "value-1")
    .withHeader("key-2", "value-2")
    .withBody("Hello")
    .to("direct:inout")
    .request(Integer.class);

다음 예제에서는 DefaultFluentProducerTemplate 오브젝트에서 프로세서를 지정하는 방법을 보여줍니다.

Integer result = DefaultFluentProducerTemplate.on(context)
    .withProcessor(exchange -> exchange.getIn().setBody("Hello World"))
    .to("direct:exception")
    .request(Integer.class);

다음 예제에서는 기본 fluent 생산자 템플릿을 사용자 지정하는 방법을 보여줍니다.

Object result = DefaultFluentProducerTemplate.on(context)
    .withTemplateCustomizer(
        template -> {
            template.setExecutorService(myExecutor);
            template.setMaximumCacheSize(10);
        }
    )
    .withBody("the body")
    .to("direct:start")
    .request();

FluentProducerTemplate 인스턴스를 생성하려면 Camel 컨텍스트에서 createFluentProducerTemplate() 메서드를 호출합니다. 예를 들면 다음과 같습니다.

FluentProducerTemplate fluentProducerTemplate = context.createFluentProducerTemplate();

37.3. 소비자 템플릿 사용

37.3.1. 개요

소비자 템플릿은 들어오는 메시지를 수신하기 위해 소비자 엔드포인트를 폴링하는 방법을 제공합니다. 교환 개체 또는 메시지 본문의 형태로 수신되는 메시지를 수신하도록 선택할 수 있습니다(메시지 본문이 내장형 형식 변환기를 사용하여 특정 형식으로 캐스팅될 수 있음).

37.3.2. 폴링 교환의 예

소비자 템플릿을 사용하여 다음과 같은 폴링 방법 중 하나를 사용하여 소비자 끝점을 폴링할 수 있습니다. 즉, receive() 를 차단하거나 시간 초과를 사용하여 receive()수신하거나, 즉시 반환하는NoWait() 를 받을 수 있습니다. 소비자 엔드포인트가 서비스를 나타내기 때문에 교환을 위해 폴링을 시도하기 전에 start() 를 호출하여 서비스 스레드를 시작하는 것도 중요합니다.

다음 예제에서는 blocking receive() 메서드를 사용하여 seda:foo 소비자 끝점의 교환을 폴링하는 방법을 보여줍니다.

import org.apache.camel.ProducerTemplate;
import org.apache.camel.ConsumerTemplate;
import org.apache.camel.Exchange;
...
ProducerTemplate template = context.createProducerTemplate();
ConsumerTemplate consumer = context.createConsumerTemplate();

// Start the consumer service
consumer.start();
...
template.sendBody("seda:foo", "Hello");
Exchange out = consumer.receive("seda:foo");
...
// Stop the consumer service
consumer.stop();

소비자 템플릿 인스턴스인 consumerCamelContext.createConsumerTemplate() 메서드를 사용하여 인스턴스화되고 소비자 서비스 스레드는 ConsumerTemplate.start() 를 호출하여 시작됩니다.

37.3.3. 폴링 메시지 본문의 예

다음 방법 중 하나를 사용하여 수신 메시지 본문에 소비자 끝점을 폴링할 수도 있습니다. 즉, receiveBody() 를 시간 초과로 수신하거나, 즉시 반환하는 receiveBodyNoWait() 입니다. 이전 예에서와 마찬가지로 교환을 위해 폴링을 시도하기 전에 start() 를 호출하여 서비스 스레드를 시작하는 것도 중요합니다.

다음 예제에서는 차단 receiveBody() 메서드를 사용하여 seda:foo 소비자 끝점에서 들어오는 메시지 본문을 폴링하는 방법을 보여줍니다.

import org.apache.camel.ProducerTemplate;
import org.apache.camel.ConsumerTemplate;
...
ProducerTemplate template = context.createProducerTemplate();
ConsumerTemplate consumer = context.createConsumerTemplate();

// Start the consumer service
consumer.start();
...
template.sendBody("seda:foo", "Hello");
Object body = consumer.receiveBody("seda:foo");
...
// Stop the consumer service
consumer.stop();

37.3.4. 교환을 폴링하는 방법

소비자 끝점에서 교환을 폴링하는 세 가지 기본 방법이 있습니다. 시간 초과 블록이 없는 receive(); 지정된 시간 초과 블록이 있는 receive(); 밀리초 동안 시간 초과 블록이 있는 receive(); 수신NoWait() 는 차단되지 않습니다. 소비자 끝점을 끝점 URI 또는 끝점 인스턴스로 지정할 수 있습니다.

Exchange receive(String endpointUri);
Exchange receive(String endpointUri, long timeout);
Exchange receiveNoWait(String endpointUri);

Exchange receive(Endpoint endpoint);
Exchange receive(Endpoint endpoint, long timeout);
Exchange receiveNoWait(Endpoint endpoint);

37.3.5. 메시지 본문을 폴링하는 방법

소비자 끝점에서 메시지 본문을 폴링하는 세 가지 기본 방법이 있습니다. 시간 초과 블록이 없는 receiveBody(); 지정된 기간 동안 시간 초과 블록이 있는 receiveBody(), receiveBodyNoWait() 는 차단되지 않습니다. 소비자 끝점을 끝점 URI 또는 끝점 인스턴스로 지정할 수 있습니다. 또한 이러한 메서드의 템플릿 양식을 호출하여 반환된 본문을 기본 제공 형식 변환기를 사용하여 특정 유형 T 로 변환할 수 있습니다.

Object receiveBody(String endpointUri);
Object receiveBody(String endpointUri, long timeout);
Object receiveBodyNoWait(String endpointUri);

Object receiveBody(Endpoint endpoint);
Object receiveBody(Endpoint endpoint, long timeout);
Object receiveBodyNoWait(Endpoint endpoint);

<T> T receiveBody(String endpointUri, Class<T> type);
<T> T receiveBody(String endpointUri, long timeout, Class<T> type);
<T> T receiveBodyNoWait(String endpointUri, Class<T> type);

<T> T receiveBody(Endpoint endpoint, Class<T> type);
<T> T receiveBody(Endpoint endpoint, long timeout, Class<T> type);
<T> T receiveBodyNoWait(Endpoint endpoint, Class<T> type);

38장. 구성 요소 구현

초록

이 장에서는 Apache Camel 구성 요소를 구현하는 데 사용할 수 있는 일반적인 접근 방식을 간략하게 설명합니다.

38.1. 구성 요소 아키텍처

38.1.1. 구성 요소의 팩토리 패턴

38.1.1.1. 개요

Apache Camel 구성 요소는 팩토리 패턴을 통해 서로 관련된 클래스 세트로 구성됩니다. 구성 요소의 기본 진입점은 Component 개체 자체입니다( org.apache.camel.Component 유형의 인스턴스). Component 개체를 팩토리로 사용하여 끝점 개체를 만들 수 있으며, 이 오브젝트는 소비자,프로듀서, 교환 개체를 생성하기 위한 팩토리 역할을 합니다. 이러한 관계가 요약되어 있습니다. 그림 38.1. “구성 요소 factory 패턴”

그림 38.1. 구성 요소 factory 패턴

구성 요소 팩토리 패턴

38.1.1.2. 구성 요소

구성 요소 구현은 끝점 팩토리입니다. 구성 요소 구현자의 주요 작업은 필요에 따라 새 끝점을 생성하는 Component.createEndpoint() 메서드를 구현하는 것입니다.

각 종류의 구성 요소는 끝점 URI에 표시되는 구성 요소 접두사 와 연결되어야 합니다. 예를 들어 파일 구성 요소는 일반적으로 file://tmp/messages/input 와 같은 끝점 URI에서 사용할 수 있는 파일 접두사와 연결됩니다. Apache Camel에 새 구성 요소를 설치할 때 특정 구성 요소 접두사와 구성 요소를 구현하는 클래스 이름 간의 연결을 정의해야 합니다.

38.1.1.3. endpoint

각 끝점 인스턴스는 특정 끝점 URI를 캡슐화합니다. Apache Camel이 새 엔드포인트 URI에 직면할 때마다 새 엔드포인트 인스턴스를 생성합니다. 끝점 오브젝트는 소비자 끝점 및 생산자 끝점을 생성하기 위한 팩토리이기도 합니다.

엔드포인트는 org.apache.camel.Endpoint 인터페이스를 구현해야 합니다. Endpoint 인터페이스는 다음 팩토리 방법을 정의합니다.

  • createConsumer()createPollingConsumer() Cryostat-ECDHE는 경로 시작 시 소스 끝점을 나타내는 소비자 끝점을 만듭니다.
  • 경로 끝에 대상 끝점을 나타내는 생산자 끝점을 만듭니다.Creates a producer endpoint, which represents the target endpoint at the end of a route.
  • path가 전달 및 종료되는 메시지를 캡슐화하는 교환 개체를 만듭니다.Creates an exchange object, which encapsulates the messages passed and down the route.

38.1.1.4. 소비자

소비자 끝점은 요청을 사용합니다. 항상 경로 시작 시 표시되고 수신 요청을 수신하고 발신 응답을 디스패치하는 코드를 캡슐화합니다. 서비스 지향 관점에서 볼 때 소비자는 서비스를 나타냅니다.

소비자는 org.apache.camel.Consumer 인터페이스를 구현해야 합니다. 소비자를 구현할 때 사용할 수 있는 다양한 패턴이 있습니다. 이러한 패턴은 38.1.3절. “소비자 패턴 및 스레드” 에 설명되어 있습니다.

38.1.1.5. 생산자

생산자 끝점 은 요청을 생성합니다. 항상 경로 끝에 표시되고 발신 요청을 디스패치하고 들어오는 응답을 수신하는 코드를 캡슐화합니다. 서비스 지향 관점에서 생산자는 서비스 소비자를 나타냅니다.

생산자는 org.apache.camel.Producer 인터페이스를 구현해야 합니다. 필요한 경우 생산자를 구현하여 비동기식 처리 스타일을 지원할 수 있습니다. 자세한 내용은 38.1.4절. “비동기 처리” 을 참조하십시오.

38.1.1.6. 교환

exchange 오브젝트는 관련 메시지 집합을 캡슐화합니다. 예를 들어 한 종류의 메시지 교환은 요청 메시지와 관련 응답으로 구성된 동기 호출입니다.

교환은 org.apache.camel.Exchange 인터페이스를 구현해야 합니다. 기본 구현은 많은 구성 요소 구현에 충분합니다. 그러나 추가 데이터를 교환과 연결하거나 교환이 추가 처리를 미리 정의하려는 경우 교환 구현을 사용자 정의하는 것이 유용할 수 있습니다.

38.1.1.7. 메시지

Exchange 오브젝트에는 두 가지 다른 메시지 슬롯이 있습니다.

  • 현재 메시지를 message history로 지정합니다.
  • out message Cryostat- Cryostattemporarily 응답 메시지가 있습니다.

모든 메시지 유형은 동일한 Java 오브젝트 org.apache.camel.Message 로 표시됩니다. 메시지 구현을 항상 사용자 지정할 필요는 없습니다. 기본 구현인 DefaultMessage 가 일반적으로 적합합니다.

38.1.2. 경로에서 구성 요소 사용

38.1.2.1. 개요

Apache Camel 경로는 기본적으로 org.apache.camel.Processor 유형의 프로세서 파이프라인입니다. 메시지는 process() 메서드를 호출하여 노드에서 노드로 전달되는 교환 오브젝트 E 로 캡슐화됩니다. 프로세서 파이프라인의 아키텍처는 그림 38.2. “경로의 소비자 및 Producer 인스턴스” 에 설명되어 있습니다.

그림 38.2. 경로의 소비자 및 Producer 인스턴스

경로의 소비자 및 Producer 인스턴스

38.1.2.2. 소스 끝점

경로 시작 시 org.apache.camel.Consumer 오브젝트로 표시되는 소스 엔드포인트가 있습니다. 소스 끝점은 들어오는 요청 메시지를 수락하고 응답을 디스패치합니다. 경로를 구성할 때 Apache Camel은 38.1.1절. “구성 요소의 팩토리 패턴” 에 설명된 대로 끝점 URI에서 구성 요소 접두사를 기반으로 적절한 소비자 유형을 생성합니다.

38.1.2.3. 프로세서

파이프라인의 각 중간 노드는 프로세서 오브젝트( org.apache.camel.Processor 인터페이스 구현)로 표시됩니다. 표준 프로세서(예: 필터,throttler 또는 지연기)를 삽입하거나 고유한 사용자 지정 프로세서 구현을 삽입할 수 있습니다.

38.1.2.4. 대상 끝점

경로 끝에는 org.apache.camel.Producer 오브젝트로 표시되는 대상 엔드포인트가 있습니다. 프로세서 파이프라인의 끝에 제공되므로 생산자는 프로세서 오브젝트( org.apache.camel.Processor 인터페이스 구현)이기도 합니다. 대상 끝점은 발신 요청 메시지를 보내고 들어오는 응답을 수신합니다. 경로를 구성할 때 Apache Camel은 엔드포인트 URI에서 구성 요소 접두사를 기반으로 적절한 Producer 유형을 생성합니다.

38.1.3. 소비자 패턴 및 스레드

38.1.3.1. 개요

소비자를 구현하는 데 사용되는 패턴은 들어오는 교환을 처리하는 데 사용되는 스레딩 모델을 결정합니다. 소비자는 다음 패턴 중 하나를 사용하여 구현할 수 있습니다.

38.1.3.2. 이벤트 중심 패턴

이벤트 중심 패턴에서 애플리케이션의 다른 부분(일반적으로 타사 라이브러리)에서 소비자가 구현하는 메서드를 호출할 때 들어오는 요청 처리가 시작됩니다. 이벤트 중심 소비자의 좋은 예는 Apache Camel Cryostat 구성 요소이며, 여기서 이벤트는 Cryostat 라이브러리에서 시작합니다. Cryostat 라이브러리는 handleNotification() 메서드를 호출하여 요청 processing Cryostat를 시작합니다. 예 41.4. “CryostatConsumer 구현” 에서 자세한 내용을 참조하십시오.

그림 38.3. “이벤트 기반 소비자” 이벤트 기반 소비자 패턴의 개요를 보여줍니다. 이 예제에서는 notify() 메서드에 대한 호출에 의해 처리가 트리거되는 것으로 가정합니다.

그림 38.3. 이벤트 기반 소비자

이벤트 중심 소비자를 사용하는 메시지 체인

이벤트 중심 소비자는 들어오는 요청을 다음과 같이 처리합니다.

  1. 소비자는 들어오는 이벤트를 수신하기 위한 방법을 구현해야 합니다( 그림 38.3. “이벤트 기반 소비자” 에서 이는 notify() 메서드로 표시됩니다. notify() 를 호출하는 스레드는 일반적으로 애플리케이션의 별도의 부분이므로 소비자의 스레드 정책은 외부적으로 구동됩니다.

    예를 들어, Cryostat 소비자 구현의 경우 소비자는 NotificationListener.handleNotification() 메서드를 구현하여 Cryostat에서 알림을 수신합니다. 소비자 처리를 구동하는 스레드는 Cryostat 계층 내에 생성됩니다.

  2. notify() 메서드의 본문에서 소비자는 먼저 들어오는 이벤트를 교환 오브젝트인 E 로 변환한 다음 경로의 다음 프로세서에서 process() 를 호출하여 교환 오브젝트를 인수로 전달합니다.

38.1.3.3. 예약된 폴링 패턴

예약된 폴링 패턴에서 소비자는 요청이 도착했는지 여부를 정기적으로 확인하여 들어오는 요청을 검색합니다. 요청 확인은 java.util.concurrent 라이브러리에서 제공하는 표준 패턴인 예약된 executor 서비스인 기본 제공 타이머 클래스에 의해 자동으로 예약됩니다. 예약된 executor 서비스는 시간 간격에 따라 특정 작업을 실행하고 작업 인스턴스를 실행하는 데 사용되는 스레드 풀을 관리합니다.

그림 38.4. “예약된 Poll 소비자” 예약된 폴링 소비자 패턴의 개요를 보여줍니다.

그림 38.4. 예약된 Poll 소비자

예약된 Poll 소비자

예약된 폴링 소비자는 다음과 같이 들어오는 요청을 처리합니다.

  1. 예약된 executor 서비스에는 소비자 처리를 시작하는 데 사용할 수 있는 스레드 풀이 있습니다. 예약된 각 시간 간격이 경과한 후 예약된 executor 서비스는 풀에서 사용 가능한 스레드를 가져옵니다(기본적으로 풀에는 5개의 스레드가 있음). 사용 가능한 스레드가 있는 경우 해당 스레드를 사용하여 소비자에서 poll() 메서드를 호출합니다.
  2. 소비자의 poll() 메서드는 들어오는 요청의 처리를 트리거하기 위한 것입니다. poll() 메서드의 본문에서 소비자는 들어오는 메시지를 검색하려고 시도합니다. 요청을 사용할 수 없는 경우 poll() 메서드는 즉시 반환됩니다.
  3. 요청 메시지를 사용할 수 있는 경우 소비자는 이를 교환 오브젝트에 삽입한 다음 경로의 다음 프로세서에서 process() 를 호출하여 교환 오브젝트를 인수로 전달합니다.

38.1.3.4. 폴링 패턴

폴링 패턴에서 타사가 소비자의 폴링 방법 중 하나를 호출할 때 들어오는 요청 처리가 시작됩니다.

  • receive()
  • receiveNoWait()
  • receive(긴 시간)

폴링 방법에서 호출을 시작하기 위한 정확한 메커니즘을 정의하는 구성 요소 구현에 따라 다릅니다. 이 메커니즘은 폴링 패턴에 지정되지 않습니다.

그림 38.5. “폴링 소비자” 폴링 소비자 패턴의 개요를 보여줍니다.

그림 38.5. 폴링 소비자

폴링 소비자

폴링 소비자는 수신 요청을 다음과 같이 처리합니다.

  1. 들어오는 요청 처리는 소비자의 폴링 방법 중 하나가 호출될 때마다 시작됩니다. 이러한 폴링 방법을 호출하는 메커니즘은 구성 요소 구현에 의해 정의됩니다.
  2. receive() 메서드의 본문에서 소비자는 들어오는 요청 메시지를 검색하려고 시도합니다. 현재 사용할 수 있는 메시지가 없는 경우 해당 동작은 호출된 수신 방법에 따라 달라집니다.

    • receiveNoWait() returns immediately
    • receive(long timeout) 은 지정된 시간 초과 간격을 대기합니다.[2] 반환하기 전
    • receive() 는 메시지가 수신될 때까지 대기합니다.
  3. 요청 메시지를 사용할 수 있는 경우 소비자는 이를 교환 오브젝트에 삽입한 다음 경로의 다음 프로세서에서 process() 를 호출하여 교환 오브젝트를 인수로 전달합니다.

38.1.4. 비동기 처리

38.1.4.1. 개요

생산자 끝점은 일반적으로 교환을 처리할 때 동기 패턴을 따릅니다. 파이프라인의 이전 프로세서가 생산자에서 process() 를 호출할 때, process() 메서드는 응답을 수신할 때까지 차단됩니다. 이 경우 프로세서의 스레드는 생산자가 요청을 보내고 응답을 수신할 때까지 차단된 상태로 유지됩니다.

그러나 이전 프로세서를 생산자에서 분리하여 프로세서의 스레드가 즉시 릴리스되고 process() 호출이 차단 되지 않는 경우가 있습니다. 이 경우 이전 프로세서에 process() 메서드의 비차단 버전을 호출하는 옵션을 제공하는 비동기 패턴을 사용하여 생산자를 구현해야 합니다.

다양한 구현 옵션에 대한 개요를 제공하기 위해 이 섹션에서는 생산자 엔드포인트를 구현하기 위한 동기 및 비동기 패턴에 대해 설명합니다.

38.1.4.2. 동기 생산자

그림 38.6. “동기 Producer” 는 생산자가 교환 처리를 완료할 때까지 이전 프로세서가 차단되는 동기 생산자의 개요를 보여줍니다.

그림 38.6. 동기 Producer

동기 Producer

동기 생산자는 다음과 같이 교환을 처리합니다.

  1. 파이프라인의 이전 프로세서는 생산자의 동기 프로세스() 메서드를 호출하여 동기 처리를 시작합니다. 동기 프로세스() 메서드는 단일 교환 인수를 사용합니다.
  2. process() 메서드의 본문에서 생산자는 요청(메시지 내)을 엔드포인트로 보냅니다.
  3. 교환 패턴에서 필요한 경우 생산자는 응답(아웃 메시지)이 끝점에서 수신될 때까지 기다립니다. 이 단계에서는 process() 메서드가 무기한 차단될 수 있습니다. 그러나 교환 패턴이 응답을 요청하지 않으면 process() 메서드는 요청을 보낸 직후 반환할 수 있습니다.
  4. process() 메서드가 반환되면 exchange 오브젝트에 동기 호출( Out 메시지 메시지)의 응답이 포함됩니다.

38.1.4.3. 비동기 생산자

그림 38.7. “비동기 Producer” 생산자가 하위 스레드로 교환을 처리하고 이전 프로세서는 상당한 시간 동안 차단되지 않는 비동기 생산자의 개요를 보여줍니다.

그림 38.7. 비동기 Producer

비동기 Producer

비동기 생산자는 다음과 같이 교환을 처리합니다.

  1. 프로세서에서 비동기 process() 메서드를 호출하려면 먼저 경로의 반환 부분에 대한 교환 처리를 담당하는 비동기 콜백 오브젝트를 생성해야 합니다. 비동기 콜백의 경우 프로세서는 AsyncCallback 인터페이스에서 상속하는 클래스를 구현해야 합니다.
  2. 프로세서는 생산자의 비동기 process() 메서드를 호출하여 비동기 처리를 시작합니다. 비동기 process() 메서드는 두 개의 인수를 사용합니다.

    • 교환 오브젝트
    • 동기 콜백 오브젝트
  3. process() 메서드의 본문에서 생산자는 처리 코드를 캡슐화하는 Runnable 오브젝트를 생성합니다. 그런 다음 생산자는 이 실행 가능 오브젝트의 실행을 하위 스레드에 위임합니다.
  4. 비동기 process() 메서드는 반환되므로 프로세서의 스레드가 확보됩니다. 교환 처리는 별도의 하위 스레드에서 계속됩니다.
  5. Runnable 오브젝트는 In 메시지를 엔드포인트로 전송합니다.
  6. 교환 패턴에서 필요한 경우 Runnable 오브젝트는 응답(Out 또는 Fault 메시지)이 끝점에서 수신될 때까지 대기합니다. Runnable 오브젝트는 응답이 수신될 때까지 차단됩니다.
  7. 응답이 도착하면 Runnable 개체는 응답(Out message)을 교환 오브젝트에 삽입한 다음 비동기 콜백 오브젝트에서 done() 을 호출합니다. 그런 다음 비동기 콜백은 응답 메시지(하위 스레드에서 실행)를 처리합니다.

38.2. 구성 요소 구현 방법

38.2.1. 개요

이 섹션에서는 사용자 지정 Apache Camel 구성 요소를 구현하는 데 필요한 단계를 간략하게 설명합니다.

38.2.2. 어떤 인터페이스를 구현해야 합니까?

구성 요소를 구현할 때는 일반적으로 다음 Java 인터페이스를 구현해야 합니다.

  • org.apache.camel.Component
  • org.apache.camel.Endpoint
  • org.apache.camel.Consumer
  • org.apache.camel.Producer

또한 다음 Java 인터페이스를 구현해야 할 수도 있습니다.

  • org.apache.camel.Exchange
  • org.apache.camel.Message

38.2.3. 구현 단계

일반적으로 사용자 지정 구성 요소를 다음과 같이 구현합니다.

  1. 구성 요소 인터페이스 Cryostat - CryostatA 구성 요소 개체가 끝점 팩토리 역할을 합니다. DefaultComponent 클래스를 확장하고 createEndpoint() 메서드를 구현합니다.

    39장. 구성 요소 인터페이스을 참조하십시오.

  2. Endpoint 인터페이스 Cryostat - Cryostat 엔드포인트를 구현하면 특정 URI로 식별되는 리소스가 표시됩니다. 끝점을 구현할 때 수행된 접근 방식은 소비자가 이벤트 중심 패턴, 예약된 폴링 패턴 또는 폴링 패턴을 따르는지 여부에 따라 달라집니다. 이벤트 중심 패턴의 경우 DefaultEndpoint 클래스를 확장하고 다음 메서드를 구현하여 끝점을 구현합니다.

    • createProducer()
    • createConsumer()

      예약된 폴링 패턴의 경우 ScheduledPollEndpoint 클래스를 확장하고 다음 메서드를 구현하여 끝점을 구현합니다.

    • createProducer()
    • createConsumer()

      폴링 패턴의 경우 DefaultPollingEndpoint 클래스를 확장하고 다음 메서드를 구현하여 끝점을 구현합니다.

    • createProducer()
    • createPollConsumer()

      40장. 엔드 포인트 인터페이스을 참조하십시오.

  3. 소비자 인터페이스 구현 (event-driven, scheduled poll, 또는 poll)을 구현해야 하는 패턴에 따라 소비자를 구현하는 데 사용할 수 있는 몇 가지 다른 접근 방법이 있습니다. 소비자 구현은 메시지 교환을 처리하는 데 사용되는 스레드 모델을 결정하는 데에도 매우 중요합니다.

    41.2절. “소비자 인터페이스 구현”을 참조하십시오.

  4. Producer 인터페이스 Cryostat - Cryostat를 구현하여 생산자를 구현한 후 DefaultProducer 클래스를 확장하고 process() 메서드를 구현합니다.

    42장. 생산자 인터페이스을 참조하십시오.

  5. 필요한 경우 교환 또는 메시지 인터페이스 의 기본 구현은 직접 사용할 수 있지만 경우에 따라 이러한 유형을 사용자 지정해야 할 수 있습니다.

    43장. 교환 인터페이스44장. 메시지 인터페이스 을 참조하십시오.

38.2.4. 구성 요소 설치 및 구성

다음 방법 중 하나로 사용자 지정 구성 요소를 설치할 수 있습니다.

  • CamelContext Cryostat- Cryostat- addComponent() 메서드에 구성 요소를 직접 추가하면 구성 요소가 프로그래밍 방식으로 추가됩니다.
  • Spring 구성 Cryostat- Cryostat를 사용하여 구성 요소를 추가합니다. 표준 Spring ans 요소는 구성 요소 인스턴스를 생성합니다. Cryostat의 id 속성은 구성 요소 접두사를 암시적으로 정의합니다. 자세한 내용은 38.3.2절. “구성 요소 구성”의 내용을 참조하십시오.
  • 구성 요소 Cryostat- CryostatAuto-discovery를 자동으로 검색하도록 Apache Camel을 구성하면 필요에 따라 Apache Camel이 구성 요소를 자동으로 로드합니다. 자세한 내용은 38.3.1절. “자동 검색 설정”의 내용을 참조하십시오.

38.3. 자동 검색 및 구성

38.3.1. 자동 검색 설정

38.3.1.1. 개요

자동 검색은 Apache Camel 애플리케이션에 구성 요소를 동적으로 추가할 수 있는 메커니즘입니다. 구성 요소 URI 접두사는 필요에 따라 구성 요소를 로드하는 키로 사용됩니다. 예를 들어 Apache Camel이 엔드포인트 URI, activemq://MyQName, ActiveMQ 엔드포인트가 아직 로드되지 않은 경우 Apache Camel은 activemq 접두사로 식별된 구성 요소를 검색하고 구성 요소를 동적으로 로드합니다.

38.3.1.2. 구성 요소 클래스 사용 가능

자동 검색을 구성하기 전에 사용자 정의 구성 요소 클래스가 현재 classpath에서 액세스할 수 있는지 확인해야 합니다. 일반적으로 사용자 정의 구성 요소 클래스를 JAR 파일에 번들하고 JAR 파일을 classpath에 추가합니다.

38.3.1.3. 자동 검색 구성

구성 요소의 자동 검색을 활성화하려면 구성 요소 접두사, 구성 요소 접두사 뒤에 이름이 지정된 Java 속성 파일을 생성하고 해당 파일을 다음 위치에 저장합니다.

/META-INF/services/org/apache/camel/component/component-prefix

component-prefix 속성 파일에는 다음 속성 설정이 포함되어야 합니다.

class=component-class-name

여기서 component-class-name 은 사용자 정의 구성 요소 클래스의 정규화된 이름입니다. 이 파일에서 추가 시스템 속성 설정을 정의할 수도 있습니다.

38.3.1.4. 예제

예를 들어 다음 Java 속성 파일을 생성하여 Apache Camel FTP 구성 요소에 자동 검색을 활성화할 수 있습니다.

/META-INF/services/org/apache/camel/component/ftp

다음 Java 속성 설정이 포함됩니다.

class=org.apache.camel.component.file.remote.RemoteFileComponent
참고

FTP 구성 요소의 Java 속성 파일은 JAR 파일 camel-ftp-Version.jar 에 이미 정의되어 있습니다.

38.3.2. 구성 요소 구성

38.3.2.1. 개요

Apache Camel Spring 구성 파일인 META-INF/spring/camel-context.xml 에서 구성 요소를 추가할 수 있습니다. 구성 요소를 찾기 위해 구성 요소의 URI 접두사가 Spring 구성에서 8080 요소의 ID 특성과 일치합니다. 구성 요소 접두사가 8080 요소 ID와 일치하는 경우 Apache Camel은 참조된 클래스를 인스턴스화하고 Spring 구성에 지정된 속성을 삽입합니다.

참고

이 메커니즘은 자동 검색보다 우선 순위가 있습니다. CamelContext에서 필수 ID가 있는 Spring 8080을 발견하면 자동 검색을 사용하여 구성 요소를 찾을 수 없습니다.

38.3.2.2. 구성 요소 클래스에 Cryostat 속성 정의

구성 요소 클래스에 삽입할 속성이 있는 경우 해당 속성을 빈 속성으로 정의합니다. 예를 들면 다음과 같습니다.

public class CustomComponent extends
  DefaultComponent<CustomExchange> {
    ...
    PropType getProperty() { ... }
    void setProperty(PropType v) { ...  }
}

getProperty() 메서드 및 setProperty() 메서드는 속성 값에 액세스합니다.

38.3.2.3. Spring에서 구성 요소 구성

Spring 구성 요소를 구성하려면 예 38.1. “Spring에서 구성 요소 구성” 과 같이 구성 파일 META-INF/spring/camel-context.xml 을 편집합니다.

예 38.1. Spring에서 구성 요소 구성

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
       http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">

  <camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
    <package>RouteBuilderPackage</package>
  </camelContext>

  <bean id="component-prefix" class="component-class-name">
    <property name="property" value="propertyValue"/>
   </bean>
</beans>

ID 구성 요소-prefix가 있는 Cryostat 요소는 component-class-name 구성 요소를 구성합니다. 속성 요소를 사용하여 구성 요소 인스턴스에 속성을 삽입할 수 있습니다. 예를 들어 위 예제의 속성 요소는 구성 요소에서 set 속성() 을 호출하여 속성 속성에 property 를 삽입합니다.

38.3.2.4. 예

예 38.2. “JMS 구성 요소 Spring 구성” 에는 ID가 jms 인ans 요소를 정의하여 Apache Camel의 JMS 구성 요소를 구성하는 방법의 예를 보여줍니다. 이러한 설정은 Spring 구성 파일인 camel-context.xml 에 추가됩니다.

예 38.2. JMS 구성 요소 Spring 구성

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
       http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">

  <camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
    <package>org.apache.camel.example.spring</package> 1
  </camelContext>

  <bean id="jms" class="org.apache.camel.component.jms.JmsComponent"> 2
    <property name="connectionFactory"3
       <bean class="org.apache.activemq.ActiveMQConnectionFactory">
         <property name="brokerURL"
                   value="vm://localhost?broker.persistent=false&amp;broker.useJmx=false"/> 4
       </bean>
    </property>
  </bean>
</beans>
1
CamelContext 는 지정된 Java 패키지 org.apache.camel.example.spring 에서 찾은 RouteBuilder 클래스를 자동으로 인스턴스화합니다.
2
ID가 있는 8080 요소인 jms 에서는 JMS 구성 요소를 구성합니다. polkit ID는 구성 요소의 URI 접두사에 해당합니다. 예를 들어 경로가 URI를 사용하여 끝점을 지정하는 경우 jms://MyQName, Apache Camel은 jms Ignition 요소의 설정을 사용하여 JMS 구성 요소를 자동으로 로드합니다.
3
JMS는 메시징 서비스에 대한 래퍼일 뿐입니다. JmsComponent 클래스에서 connectionFactory 속성을 설정하여 메시징 시스템의 구체적인 구현을 지정해야 합니다.
4
이 예제에서 JMS 메시징 서비스의 구체적인 구현은 Apache ActiveMQ입니다. brokerURL 속성은 메시지 브로커가 로컬 JVM(Java 가상 시스템)에 포함된 ActiveMQ 브로커 인스턴스에 대한 연결을 초기화합니다. JVM에 브로커가 아직 존재하지 않는 경우 ActiveMQ는 options broker.persistent=false ( broker가 메시지를 유지하지 않음) 및 broker.useJmx=false (임시 포트를 열지 않음)로 인스턴스화합니다.


[2] 시간 초과 간격은 일반적으로 밀리초 단위로 지정됩니다.

39장. 구성 요소 인터페이스

초록

이 장에서는 Component 인터페이스를 구현하는 방법을 설명합니다.

39.1. 구성 요소 인터페이스

39.1.1. 개요

Apache Camel 구성 요소를 구현하려면 org.apache.camel.Component 인터페이스를 구현해야 합니다. 구성 요소 유형 인스턴스는 사용자 지정 구성 요소에 진입점을 제공합니다.An instance of Component type provides the entry point into a custom component. 즉, 구성 요소의 다른 모든 개체는 궁극적으로 Component 인스턴스를 통해 액세스할 수 있습니다. 그림 39.1. “구성 요소 상속 계층 구조” 구성 요소 상속 계층을 구성하는 관련 Java 인터페이스 및 클래스를 표시합니다.

그림 39.1. 구성 요소 상속 계층 구조

구성 요소 상속 계층

39.1.2. 구성 요소 인터페이스

예 39.1. “구성 요소 인터페이스” org.apache.camel.Component 인터페이스의 정의를 보여줍니다.

예 39.1. 구성 요소 인터페이스

package org.apache.camel;

public interface Component {
    CamelContext getCamelContext();
    void setCamelContext(CamelContext context);

    Endpoint createEndpoint(String uri) throws Exception;
}

39.1.3. 구성 요소 메서드

구성 요소 인터페이스는 다음 메서드를 정의합니다.

  • getCamelContext()setCamelContext() Cryostat- CryostatReferences 이 Component가 속한 CamelContext 를 설정합니다. setCamelContext() 메서드는 구성 요소를 CamelContext 에 추가할 때 자동으로 호출됩니다.
  • createEndpoint() 이 구성 요소의 끝점 인스턴스를 생성하기 위해 호출되는 팩토리 메서드입니다. uri 매개변수는 엔드포인트를 생성하는 데 필요한 세부 정보가 포함된 엔드포인트 URI입니다.

39.2. 구성 요소 인터페이스 구현

39.2.1. DefaultComponent 클래스

일부 메서드에 대한 표준 기능 및 기본 구현을 제공하는 org.apache.camel.impl.DefaultComponent 클래스를 확장하여 새 구성 요소를 구현합니다. 특히 DefaultComponent 클래스는 URI 구문 분석을 지원하고 예약된 executor(예약된 폴링 패턴에 사용)를 생성합니다.

39.2.2. URI 구문 분석

기본 구성 요소 인터페이스에 정의된 createEndpoint(String uri) 메서드는 유일한 인수로 작성되지 않은 완전한 엔드포인트 URI를 사용합니다. 반면 DefaultComponent 클래스는 다음 시그니처와 함께 createEndpoint() 메서드의 세 가지 통합 버전을 정의합니다.

protected abstract Endpoint createEndpoint(
    String uri,
    String remaining,
    Map parameters
)
throws Exception;

URI는 원래의 정리되지 않은 URI입니다. 나머지는 시작 시 구성 요소 접두사를 제거하고 끝에 쿼리 옵션을 중단한 후 남은 URI의 일부이며, 매개 변수에 는 구문 분석된 쿼리 옵션이 포함됩니다. DefaultComponent 에서 상속할 때 재정의해야 하는 createEndpoint() 메서드의 이 버전입니다. 이는 엔드포인트 URI를 이미 구문 분석하는 이점이 있습니다.

파일 구성 요소에 대한 다음 샘플 끝점 URI에서는 URI 구문 분석이 실제로 작동하는 방식을 보여줍니다.

file:///tmp/messages/foo?delete=true&moveNamePostfix=.old

이 URI에서 다음 인수는 createEndpoint() 의 세 가지 통합 버전에 전달됩니다.

인수샘플 값

uri

file:///tmp/messages/foo?delete=true&moveNamePostfix=.old

남아 있음

/tmp/messages/foo

parameters

두 개의 항목은 java.util.Map 에서 설정됩니다.

  • 매개 변수 삭제 는 부울 true입니다.
  • 매개변수 moveNamePostfix 에는 문자열 값 .old 가 있습니다.

39.2.3. 매개변수 삽입

기본적으로 URI 쿼리 옵션에서 추출된 매개 변수는 끝점의 빈 속성에 삽입됩니다. DefaultComponent 클래스는 매개변수를 자동으로 삽입합니다.

예를 들어 두 가지 URI 쿼리 옵션인 deletemoveNamePostfix 를 지원하는 사용자 정의 끝점을 정의하려는 경우입니다. 엔드포인트 클래스에서 해당 8080 메서드(getECDSA 및 setECDSA)를 정의하는 것은 모두 수행해야 합니다.

public class FileEndpoint extends ScheduledPollEndpoint {
    ...
    public boolean isDelete() {
        return delete;
    }
    public void setDelete(boolean delete) {
        this.delete = delete;
    }
    ...
    public String getMoveNamePostfix() {
        return moveNamePostfix;
    }
    public void setMoveNamePostfix(String moveNamePostfix) {
        this.moveNamePostfix = moveNamePostfix;
    }
}

또한 소비자 매개변수에 URI 쿼리 옵션을 삽입할 수도 있습니다. 자세한 내용은 “소비자 매개변수 삽입”의 내용을 참조하십시오.

39.2.4. 끝점 매개변수 삽입 비활성화

Endpoint 클래스에 정의된 매개변수가 없는 경우 엔드포인트 매개 변수 주입을 비활성화하여 끝점 생성 프로세스를 최적화할 수 있습니다. 끝점에서 매개변수 삽입을 비활성화하려면 useIntrospectionOnEndpoint() 메서드를 재정의하고 다음과 같이 false 를 반환하도록 구현합니다.

protected boolean useIntrospectionOnEndpoint() {
  return false;
}
참고

useIntrospectionOnEndpoint() 메서드는 소비자 클래스에서 수행할 수 있는 매개 변수 주입에 영향을 미치지 않습니다. 해당 수준에서 매개변수 삽입은 Endpoint.configureProperties() 메서드에서 제어합니다( 40.2절. “끝점 인터페이스 구현”참조).

39.2.5. 예약된 executor 서비스

예약된 executor는 예약된 폴링 패턴에서 사용되며, 소비자 끝점의 주기적인 폴링을 주도합니다(예약된 executor는 효과적으로 스레드 풀 구현임).

예약된 executor 서비스를 인스턴스화하려면 CamelContext.getExecutorServiceStrategy() 메서드에서 반환하는 ExecutorServiceStrategy 오브젝트를 사용합니다. Apache Camel 스레딩 모델에 대한 자세한 내용은 2.8절. “스레드 모델” 에서 참조하십시오.

참고

Apache Camel 2.3 이전에는 DefaultComponent 클래스에서 스레드 풀 인스턴스를 생성하기 위한 getExecutorService() 메서드를 제공했습니다. 그러나 2.3 이후 스레드 풀 생성은 이제 ExecutorServiceStrategy 개체에 의해 중앙에서 관리됩니다.

39.2.6. URI 검증

끝점 인스턴스를 만들기 전에 URI의 유효성을 검사하려면 다음 서명이 있는 DefaultComponent 클래스에서 validateURI() 메서드를 재정의할 수 있습니다.

protected void validateURI(String uri,
                           String path,
                           Map parameters)
   throws ResolveEndpointFailedException;

제공된 URI에 필요한 형식이 없는 경우 validateURI() 를 구현하면 org.apache.camel.ResolveEndpointFailedException 예외가 발생합니다.

39.2.7. 끝점 생성

예 39.2. “Implementation of createEndpoint() 필요에 따라 엔드포인트 인스턴스를 생성하는 DefaultComponent.createEndpoint() 메서드를 구현하는 방법을 간략하게 설명합니다.

예 39.2. Implementation of createEndpoint()

public class CustomComponent extends DefaultComponent { 1
    ...
    protected Endpoint createEndpoint(String uri, String remaining, Map parameters) throws Exception { 2
        CustomEndpoint result = new CustomEndpoint(uri, this); 3
        // ...
        return result;
    }
}
1
CustomComponentDefaultComponent 클래스를 확장하여 정의된 사용자 지정 구성 요소 클래스의 이름입니다.
2
DefaultComponent 를 확장하는 경우 세 개의 인수를 사용하여 createEndpoint() 메서드를 구현해야 합니다( “URI 구문 분석”참조).
3
해당 생성자를 호출하여 사용자 지정 끝점 유형인 CustomEndpoint 의 인스턴스를 만듭니다. 최소한 이 생성자는 원래 URI 문자열 uri 의 복사본과 이 구성 요소 인스턴스에 대한 참조를 가져옵니다.

39.2.8. 예제

예 39.3. “FileComponent Implementation” FileComponent 클래스의 샘플 구현을 보여 줍니다.Shows a sample implementation of a FileComponent class.

예 39.3. FileComponent Implementation

package org.apache.camel.component.file;

import org.apache.camel.CamelContext;
import org.apache.camel.Endpoint;
import org.apache.camel.impl.DefaultComponent;

import java.io.File;
import java.util.Map;

public class FileComponent extends DefaultComponent {
    public static final String HEADER_FILE_NAME = "org.apache.camel.file.name";

    public FileComponent() { 1
    }

    public FileComponent(CamelContext context) { 2
        super(context);
    }

    protected Endpoint createEndpoint(String uri, String remaining, Map parameters) throws Exception { 3
        File file = new File(remaining);
        FileEndpoint result = new FileEndpoint(file, uri, this);
        return result;
    }
}
1
클래스의 자동 인스턴스화를 용이하게 하기 위해 구성 요소 클래스에 대한 no-argument 생성자를 항상 정의합니다.
2
상위 CamelContext 인스턴스를 인수로 사용하는 생성자는 프로그래밍을 통해 구성 요소 인스턴스를 생성할 때 편리합니다.
3
FileComponent.createEndpoint() 메서드의 구현은 예 39.2. “Implementation of createEndpoint() 에 설명된 패턴을 따릅니다. 구현에서 FileEndpoint 오브젝트를 생성합니다.

39.2.9. SynchronizationRouteAware 인터페이스

SynchronizationRouteAware 인터페이스를 사용하면 교환이 라우팅되기 전과 후에 콜백을 사용할 수 있습니다.

  • OnBeforeRoute: 지정된 경로에서 교환을 라우팅하기 전에 취소되었습니다. 그러나 경로를 시작한 후 UnitOfWorkSynchronizationRouteAware 구현을 추가하는 경우 이 콜백이 호출되지 않을 수 있습니다.
  • OnAfterRoute: 지정된 경로에서 교환을 라우팅한 후 수신됩니다. 그러나 교환이 여러 경로를 통해 라우팅되는 경우 각 경로에 대한 호출 백이 생성됩니다.

    이 호출은 다음 콜백 전에 수행됩니다.

    1. 경로 소비자는 모든 응답을 호출자에 다시 씁니다( InOut 모드인 경우)
    2. UnitOfWorkSynchronization.onComplete(org.apache.camel.Exchange) 또는 Synchronization.onFailure(org.apache.camel.Exchange)를 호출하여 수행됩니다.

40장. 엔드 포인트 인터페이스

초록

이 장에서는 Apache Camel 구성 요소를 구현하는 데 중요한 단계인 Endpoint 인터페이스를 구현하는 방법을 설명합니다.

40.1. 끝점 인터페이스

40.1.1. 개요

org.apache.camel.Endpoint 유형의 인스턴스는 엔드포인트 URI를 캡슐화하며 Consumer,ProducerExchange 오브젝트의 팩토리 역할을 합니다. 끝점을 구현하는 세 가지 방법이 있습니다.

  • 이벤트 중심
  • 예약된 폴링
  • 폴링

이러한 끝점 구현 패턴은 소비자 Cryostat- Cryostat 참조 41.2절. “소비자 인터페이스 구현” 를 구현하기 위한 해당 패턴을 보완합니다.

그림 40.1. “엔드포인트 상속 계층 구조” 엔드포인트 상속 계층 구조를 구성하는 관련 Java 인터페이스 및 클래스를 표시합니다.

그림 40.1. 엔드포인트 상속 계층 구조

끝점 상속 계층

40.1.2. 끝점 인터페이스

예 40.1. “엔드 포인트 인터페이스” org.apache.camel.Endpoint 인터페이스의 정의를 보여줍니다.

예 40.1. 엔드 포인트 인터페이스

package org.apache.camel;

public interface Endpoint {
    boolean isSingleton();

    String getEndpointUri();

    String getEndpointKey();

    CamelContext getCamelContext();
    void setCamelContext(CamelContext context);

    void configureProperties(Map options);

    boolean isLenientProperties();

    Exchange createExchange();
    Exchange createExchange(ExchangePattern pattern);
    Exchange createExchange(Exchange exchange);

    Producer createProducer() throws Exception;

    Consumer createConsumer(Processor processor) throws Exception;
    PollingConsumer createPollingConsumer() throws Exception;
}

40.1.3. 끝점 방법

Endpoint 인터페이스는 다음 방법을 정의합니다.

  • isSingleton() Cryostat- Cryostat true, 각 URI가 CamelContext 내에서 단일 끝점에 매핑되도록 하려면 true입니다. 이 속성이 true 인 경우 경로 내의 동일한 URI에 대한 여러 참조는 항상 단일 끝점 인스턴스를 나타냅니다. 반면 이 속성이 false 인 경우 경로 내의 동일한 URI에 대한 여러 참조가 고유한 엔드포인트 인스턴스를 나타냅니다. 경로의 URI를 참조할 때마다 새 엔드포인트 인스턴스가 생성됩니다.
  • getEndpointUri() 이 끝점의 엔드포인트 URI를 반환합니다.
  • 엔드포인트를 등록할 때 org.apache.camel.spi.LifecycleStrategy 에 의해 사용되는 getEndpointKey() Cryostat- CryostatUsed
  • getCamelContext() Cryostat- Cryostat 이 엔드포인트가 속한 CamelContext 인스턴스에 대한 참조를 반환합니다.
  • setCamelContext() Cryostat-이 끝점이 속한 CamelContext 인스턴스를 설정합니다.
  • ConfigureProperties() Cryostat- CryostatStores 새 Consumer 인스턴스를 생성할 때 매개 변수를 삽입하는 데 사용되는 매개변수 맵의 복사본입니다.
  • URI에 알 수 없는 매개변수(즉, Endpoint 또는 Consumer 클래스에서 삽입할 수 없는 매개 변수)를 포함하는 것이 허용됨을 나타내는 isLenientProperties() 밀리초 true. 일반적으로 이 방법은 false 를 반환하도록 구현해야 합니다.
  • 다음과 같은 변형을 사용하여 오버로드된 메서드를 만듭니다.Recording an overloaded method with the following variants:

    • exchange createExchange() Cryostat-가 기본 교환 패턴 설정으로 새 교환 인스턴스를 만듭니다.
    • exchange createExchange(ExchangePattern 패턴) Cryostat-가 지정된 교환 패턴을 사용하여 새 교환 인스턴스를 만듭니다.
    • Exchange createExchange(Exchange 교환) Cryostat- Cryostat는 지정된 교환 인수를 이 엔드포인트에 필요한 교환 유형으로 변환합니다. 지정된 교환이 올바른 유형이 아닌 경우 이 방법은 올바른 유형의 새 인스턴스에 복사합니다. 이 메서드의 기본 구현은 DefaultEndpoint 클래스에 제공됩니다.
  • createProducer() Cryostat- CryostatFactory 메서드를 사용하여 새 Producer 인스턴스를 생성합니다.
  • createConsumer() Cryostat- CryostatFactory 메서드를 사용하여 새 이벤트 기반 소비자 인스턴스를 생성합니다. 프로세서 인수는 경로의 첫 번째 프로세서에 대한 참조입니다.
  • 새 폴링 소비자 인스턴스를 생성하기 위해 createPollingConsumer() Cryostat- CryostatFactory 메서드.

40.1.4. 끝점 싱글톤

불필요한 오버헤드를 방지하려면 동일한 URI( CamelContext 포함)가 있는 모든 끝점에 대해 단일 엔드포인트 인스턴스를 생성하는 것이 좋습니다. isSingleton() 을 구현하여 이 조건을 적용하여 true 를 반환할 수 있습니다.

참고

이 컨텍스트에서 동일한 URI 는 문자열 같음을 사용하여 비교할 때 두 URI가 동일하다는 것을 의미합니다. 기본적으로 다른 문자열로 표현되지만 동일한 URI를 두 개 가질 수 있습니다. 이 경우 URI를 동일한 것으로 취급하지 않습니다.

40.2. 끝점 인터페이스 구현

40.2.1. 끝점을 구현하는 다른 방법

다음과 같은 대체 끝점 구현 패턴이 지원됩니다.

40.2.2. 이벤트 중심 끝점 구현

사용자 지정 끝점이 이벤트 중심 패턴을 준수하는 경우 38.1.3절. “소비자 패턴 및 스레드”에 표시된 것처럼 abstract 클래스 org.apache.camel.impl.DefaultEndpoint 를 확장하여 구현됩니다. 예 40.2. “DefaultEndpoint 구현”

예 40.2. DefaultEndpoint 구현

import java.util.Map;
import java.util.concurrent.BlockingQueue;

import org.apache.camel.Component;
import org.apache.camel.Consumer;
import org.apache.camel.Exchange;
import org.apache.camel.Processor;
import org.apache.camel.Producer;
import org.apache.camel.impl.DefaultEndpoint;
import org.apache.camel.impl.DefaultExchange;

public class CustomEndpoint extends DefaultEndpoint { 1

    public CustomEndpoint(String endpointUri, Component component) { 2
        super(endpointUri, component);
        // Do any other initialization...
    }

    public Producer createProducer() throws Exception { 3
        return new CustomProducer(this);
    }

    public Consumer createConsumer(Processor processor) throws Exception { 4
        return new CustomConsumer(this, processor);
    }

    public boolean isSingleton() {
        return true;
    }

    // Implement the following methods, only if you need to set exchange properties.
    //
    public Exchange createExchange() { 5
        return this.createExchange(getExchangePattern());
    }

    public Exchange createExchange(ExchangePattern pattern) {
        Exchange result = new DefaultExchange(getCamelContext(), pattern);
        // Set exchange properties
        ...
        return result;
    }
}
1
DefaultEndpoint 클래스를 확장하여 이벤트 기반 사용자 지정 끝점인 CustomEndpoint 를 구현합니다.
2
끝점 URI, endpointUri 및 상위 구성 요소 참조, 구성 요소를 인수로 사용하는 생성자가 하나 이상 있어야 합니다.
3
createProducer() 팩토리 메서드를 구현하여 생산자 엔드포인트를 생성합니다.
4
createConsumer() 팩토리 메서드를 구현하여 이벤트 중심 소비자 인스턴스를 생성합니다.
5
일반적으로 createExchange() 메서드를 재정의할 필요가 없습니다. DefaultEndpoint 에서 상속된 구현은 기본적으로 모든 Apache Camel 구성 요소에서 사용할 수 있는 DefaultExchange 오브젝트를 생성합니다. 그러나 DefaultExchange 개체에서 일부 교환 속성을 초기화해야 하는 경우 교환 속성 설정을 추가하기 위해 여기에서 createExchange() 메서드를 재정의하는 것이 적절합니다.
중요

createPollingConsumer() 메서드를 재정의 하지 마십시오.

DefaultEndpoint 클래스는 사용자 지정 엔드포인트 코드를 작성할 때 유용할 수 있는 다음 메서드의 기본 구현을 제공합니다.

  • getEndpointUri() 엔드포인트 URI를 다시 시도합니다.
  • getCamelContext() Cryostat- Cryostat에 대한 참조로 CamelContext 에 대한 참조입니다.
  • getComponent() Cryostat- parent 구성 요소에 대한 참조입니다.
  • createPollingConsumer() Cryostat- Cryostat는 폴링 소비자를 만듭니다. 생성된 폴링 소비자 기능은 이벤트 중심 소비자를 기반으로 합니다. 이벤트 중심 소비자 메서드를 재정의하는 경우 createConsumer() 를 사용하면 폴링 소비자 구현을 얻을 수 있습니다.
  • CreateExchange(Exchange e) Cryostat- Cryostat는 지정된 교환 오브젝트( e )를 이 끝점에 필요한 유형으로 변환합니다. 이 메서드는 재정의된 createExchange() 엔드포인트를 사용하여 새 엔드포인트를 생성합니다. 이렇게 하면 해당 방법이 사용자 지정 교환 유형에서도 작동합니다.

40.2.3. 예약된 폴링 끝점 구현

사용자 정의 끝점이 예약된 폴링 패턴을 준수하는 경우 38.1.3절. “소비자 패턴 및 스레드”에 표시된 것처럼 org.apache.camel.impl.ScheduledPollEndpoint 에서 상속하여 구현됩니다. 예 40.3. “ScheduledPollEndpoint 구현”

예 40.3. ScheduledPollEndpoint 구현

import org.apache.camel.Consumer;
import org.apache.camel.Processor;
import org.apache.camel.Producer;
import org.apache.camel.ExchangePattern;
import org.apache.camel.Message;
import org.apache.camel.impl.ScheduledPollEndpoint;

public class CustomEndpoint extends ScheduledPollEndpoint {  1

    protected CustomEndpoint(String endpointUri, CustomComponent component) { 2
        super(endpointUri, component);
        // Do any other initialization...
    }

    public Producer createProducer() throws Exception { 3
        Producer result = new CustomProducer(this);
        return result;
    }

    public Consumer createConsumer(Processor processor) throws Exception { 4
        Consumer result = new CustomConsumer(this, processor);
        configureConsumer(result); 5
        return result;
    }

    public boolean isSingleton() {
        return true;
    }

    // Implement the following methods, only if you need to set exchange properties.
    //
    public Exchange createExchange() { 6
        return this.createExchange(getExchangePattern());
    }

    public Exchange createExchange(ExchangePattern pattern) {
        Exchange result = new DefaultExchange(getCamelContext(), pattern);
        // Set exchange properties
        ...
        return result;
    }
}
1
ScheduledPollEndpoint 클래스를 확장하여 예약된 폴링 사용자 지정 엔드포인트인 CustomEndpoint 를 구현합니다.
2
엔드포인트 URI, endpointUri 및 상위 구성 요소 참조, 구성 요소를 인수로 사용하는 생성자가 하나 이상 있어야 합니다.
3
createProducer() 팩토리 메서드를 구현하여 생산자 엔드포인트를 생성합니다.
4
createConsumer() 팩토리 메서드를 구현하여 예약된 폴링 소비자 인스턴스를 생성합니다.
5
ScheduledPollEndpoint 기본 클래스에 정의된 configureConsumer() 메서드는 소비자 쿼리 옵션을 소비자에 주입합니다. “소비자 매개변수 삽입”을 참조하십시오.
6
일반적으로 createExchange() 메서드를 재정의할 필요가 없습니다. DefaultEndpoint 에서 상속된 구현은 기본적으로 모든 Apache Camel 구성 요소에서 사용할 수 있는 DefaultExchange 오브젝트를 생성합니다. 그러나 DefaultExchange 개체에서 일부 교환 속성을 초기화해야 하는 경우 교환 속성 설정을 추가하기 위해 여기에서 createExchange() 메서드를 재정의하는 것이 적절합니다.
중요

createPollingConsumer() 메서드를 재정의 하지 마십시오.

40.2.4. 폴링 끝점 구현

사용자 정의 끝점이 폴링 소비자 패턴을 준수하는 경우 38.1.3절. “소비자 패턴 및 스레드”에 표시된 것처럼 abstract 클래스 org.apache.camel.impl.DefaultPollingEndpoint 에서 상속하여 구현됩니다. 예 40.4. “DefaultPollingEndpoint 구현”

예 40.4. DefaultPollingEndpoint 구현

import org.apache.camel.Consumer;
import org.apache.camel.Processor;
import org.apache.camel.Producer;
import org.apache.camel.ExchangePattern;
import org.apache.camel.Message;
import org.apache.camel.impl.DefaultPollingEndpoint;

public class CustomEndpoint extends DefaultPollingEndpoint {
    ...
    public PollingConsumer createPollingConsumer() throws Exception {
        PollingConsumer result = new CustomConsumer(this);
        configureConsumer(result);
        return result;
    }

    // Do NOT implement createConsumer(). It is already implemented in DefaultPollingEndpoint.
    ...
}

CustomEndpoint 클래스는 폴링 끝점이므로 createConsumer() 메서드 대신 createPollingConsumer() 메서드를 구현해야 합니다. createPollingConsumer() 에서 반환된 소비자 인스턴스는 PollingConsumer 인터페이스에서 상속해야 합니다. 폴링 소비자를 구현하는 방법에 대한 자세한 내용은 “폴링 소비자 구현” 을 참조하십시오.

createPollingConsumer() 메서드 구현 외에도 DefaultPollingEndpoint 를 구현하는 단계는 ScheduledPollEndpoint 를 구현하는 단계와 유사합니다. 자세한 내용은 예 40.3. “ScheduledPollEndpoint 구현” 을 참조하십시오.

40.2.5. BrowsableEndpoint 인터페이스 구현

현재 끝점에서 보류 중인 교환 인스턴스 목록을 노출하려면 예 40.5. “BrowsableEndpoint 인터페이스” 에 표시된 것처럼 org.apache.camel.spi.BrowsableEndpoint 인터페이스를 구현할 수 있습니다. 끝점이 들어오는 이벤트의 버퍼링을 수행하는 경우 이 인터페이스를 구현하는 것이 좋습니다. 예를 들어 Apache Camel SEDA 끝점은 BrowsableEndpoint 인터페이스 Cryostat- Cryostat 참조 예 40.6. “SedaEndpoint 구현” 를 구현합니다.

예 40.5. BrowsableEndpoint 인터페이스

package org.apache.camel.spi;

import java.util.List;

import org.apache.camel.Endpoint;
import org.apache.camel.Exchange;

public interface BrowsableEndpoint extends Endpoint {
    List<Exchange> getExchanges();
}

40.2.6. 예제

예 40.6. “SedaEndpoint 구현” SedaEndpoint 의 샘플 구현을 보여줍니다. SEDA 엔드포인트는 이벤트 중심 엔드포인트 의 예입니다. 들어오는 이벤트는 FIFO 대기열( java.util.concurrent.BlockingQueue의 인스턴스)에 저장되고 SEDA 소비자는 이벤트를 읽고 처리하기 위해 스레드를 시작합니다. 이벤트 자체는 org.apache.camel.Exchange 오브젝트로 표시됩니다.

예 40.6. SedaEndpoint 구현

package org.apache.camel.component.seda;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.BlockingQueue;

import org.apache.camel.Component;
import org.apache.camel.Consumer;
import org.apache.camel.Exchange;
import org.apache.camel.Processor;
import org.apache.camel.Producer;
import org.apache.camel.impl.DefaultEndpoint;
import org.apache.camel.spi.BrowsableEndpoint;

public class SedaEndpoint extends DefaultEndpoint implements BrowsableEndpoint { 1
    private BlockingQueue<Exchange> queue;

    public SedaEndpoint(String endpointUri, Component component, BlockingQueue<Exchange> queue) { 2
        super(endpointUri, component);
        this.queue = queue;
    }

    public SedaEndpoint(String uri, SedaComponent component, Map parameters) { 3
        this(uri, component, component.createQueue(uri, parameters));
    }

    public Producer createProducer() throws Exception { 4
        return new CollectionProducer(this, getQueue());
    }

    public Consumer createConsumer(Processor processor) throws Exception { 5
        return new SedaConsumer(this, processor);
    }

    public BlockingQueue<Exchange> getQueue() { 6
        return queue;
    }

    public boolean isSingleton() { 7
        return true;
    }

    public List<Exchange> getExchanges() { 8
        return new ArrayList<Exchange> getQueue());
    }
}
1
SedaEndpoint 클래스는 DefaultEndpoint 클래스를 확장하여 이벤트 중심 엔드포인트를 구현하기 위한 패턴을 따릅니다. SedaEndpoint 클래스는 큐의 교환 개체 목록에 대한 액세스를 제공하는 BrowsableEndpoint 인터페이스도 구현합니다.
2
이벤트 중심 소비자의 일반적인 패턴에 따라 SedaEndpoint 는 엔드포인트 인수, endpointUri 및 구성 요소 참조 인수인 구성 요소를 사용하는 생성자를 정의합니다.
3
큐 생성을 부모 구성 요소 인스턴스에 위임하는 또 다른 생성자가 제공됩니다.
4
createProducer() 팩토리 메서드는 이벤트를 큐에 추가하는 생산자 구현인 CollectionProducer 의 인스턴스를 생성합니다.
5
createConsumer() 팩토리 메서드는 큐에서 이벤트를 가져오고 처리하는 SedaConsumer 의 인스턴스를 생성합니다.
6
getQueue() 메서드는 큐에 대한 참조를 반환합니다.
7
isSingleton() 메서드는 각 고유 URI 문자열에 대해 단일 엔드포인트 인스턴스를 생성해야 함을 나타내는 true 를 반환합니다.
8
getExchanges() 메서드는 BrowsableEndpoint에서 해당 추상 메서드를 구현합니다.

41장. 소비자 인터페이스

초록

이 장에서는 Apache Camel 구성 요소를 구현하는 데 중요한 단계인 Consumer 인터페이스를 구현하는 방법을 설명합니다.

41.1. 소비자 인터페이스

41.1.1. 개요

org.apache.camel.Consumer 유형의 인스턴스는 경로의 소스 끝점을 나타냅니다. 소비자를 구현하는 방법에는 여러 가지가 있으며( 38.1.3절. “소비자 패턴 및 스레드”참조) 이러한 유연성은 소비자를 구현하기 위한 여러 가지 기본 클래스를 포함하는 상속 계층( 그림 41.1. “소비자 상속 계층 구조”참조)에 반영됩니다.

그림 41.1. 소비자 상속 계층 구조

소비자 상속 계층

41.1.2. 소비자 매개변수 삽입

예약된 폴링 패턴을 따르는 소비자의 경우( “예약된 폴링 패턴”참조) Apache Camel은 소비자 인스턴스에 매개변수 삽입을 지원합니다. 예를 들어 사용자 지정 접두사로 식별되는 구성 요소에 대해 다음 끝점 URI를 고려하십시오.

custom:destination?consumer.myConsumerParam

Apache Camel은 소비자의 쿼리 옵션을 자동으로 삽입할 수 있도록 지원합니다.\*. consumer.myConsumerParam 매개변수의 경우 다음과 같이 Consumer 구현 클래스에서 해당 setter 및 getter 메서드를 정의해야 합니다.

public class CustomConsumer extends ScheduledPollConsumer {
    ...
    String getMyConsumerParam() { ... }
    void setMyConsumerParam(String s) { ... }
    ...
}

여기서 getter 및 setter 메서드는 일반적인 Java 빈 규칙을 따릅니다(속성 이름의 첫 번째 문자를 대문자 포함).

Consumer 구현에서 Quarkus 메서드를 정의하는 것 외에도 Endpoint.createConsumer() ()를 구현할 때 configureConsumer() 메서드를 호출해야 합니다( “예약된 폴링 끝점 구현”참조).

예 41.1. “FileEndpoint createConsumer() 구현” 파일 구성 요소의 FileEndpoint 클래스에서 가져온 createConsumer() 메서드 구현 예를 보여줍니다.

예 41.1. FileEndpoint createConsumer() 구현

...
public class FileEndpoint extends ScheduledPollEndpoint {
    ...
    public Consumer createConsumer(Processor processor) throws Exception {
        Consumer result = new FileConsumer(this, processor);
        configureConsumer(result);
        return result;
    }
    ...
    }

런타임 시 소비자 매개변수 삽입은 다음과 같이 작동합니다.

  1. 엔드포인트가 생성되면 DefaultComponent.createEndpoint(String uri) 의 기본 구현은 소비자 매개 변수를 추출하기 위해 URI를 구문 분석하고 ScheduledPollEndpoint.configureProperties() 를 호출하여 엔드포인트 인스턴스에 저장합니다.
  2. createConsumer() 가 호출되면 메서드 구현에서 configureConsumer() 를 호출하여 소비자 매개변수를 삽입합니다( 예 41.1. “FileEndpoint createConsumer() 구현”참조).
  3. configureConsumer() 메서드는 Java 리플렉션을 사용하여 소비자가 제거된 후 이름이 관련 옵션과 일치하는 setter 메서드를 호출합니다.

41.1.3. 예약된 폴링 매개변수

예약된 폴링 패턴을 따르는 소비자는 표 41.1. “예약된 Poll 매개변수” 에 표시된 소비자 매개변수( endpoint URI에서 쿼리 옵션으로 표시될 수 있음)를 자동으로 지원합니다.

표 41.1. 예약된 Poll 매개변수

이름기본설명

initialDelay

1000

첫 번째 폴링 전 지연(밀리초)입니다.

delay

500

useFixedDelay 플래그의 값에 따라 달라집니다(시간 단위는 밀리초).

useFixedDelay

false

false 인 경우 delay 매개변수가 폴링 기간으로 해석됩니다. 폴링은 initialDelay,initialDelay+delay,initialDelay+2\*delay 등에서 발생합니다.

true 인 경우 delay 매개변수는 이전 실행과 다음 실행 사이에 경과된 시간으로 해석됩니다. 폴링은 initialDelay,initialDelay+[ProcessingTime]+delay 에서 발생합니다. 여기서 ProcessingTime 은 현재 스레드에서 교환 개체를 처리하는 데 걸린 시간입니다.

41.1.4. 이벤트 중심 소비자와 폴링 소비자 간 변환

Apache Camel은 이벤트 중심 소비자와 폴링 소비자 간에 변환하는 데 사용할 수 있는 두 가지 특수 소비자 구현을 제공합니다. 다음과 같은 변환 클래스가 제공됩니다.

  • org.apache.camel.impl.EventDrivenPollingConsumer Cryostat- Cryostat는 이벤트 중심 소비자 인스턴스를 폴링 소비자 인스턴스로 변환합니다.
  • org.apache.camel.impl.DefaultScheduledPollConsumer Cryostat- Cryostat는 폴링 소비자를 이벤트 중심 소비자 인스턴스로 변환합니다.

실제로 이러한 클래스는 끝점 유형을 구현하는 작업을 단순화하는 데 사용됩니다. Endpoint 인터페이스는 소비자 인스턴스를 생성하는 다음 두 가지 방법을 정의합니다.

package org.apache.camel;

public interface Endpoint {
    ...
    Consumer createConsumer(Processor processor) throws Exception;
    PollingConsumer createPollingConsumer() throws Exception;
}

createConsumer() 는 이벤트 중심 소비자를 반환하고 createPollingConsumer() 는 폴링 소비자를 반환합니다. 이러한 방법 중 하나만 구현합니다. 예를 들어 소비자에 대한 이벤트 중심 패턴을 따르는 경우 createConsumer() 메서드를 구현하여 예외를 발생시키는 createPollingConsumer() 에 대한 메서드 구현을 제공합니다. 그러나 변환 클래스를 사용하면 Apache Camel에서 보다 유용한 기본 구현을 제공할 수 있습니다.

예를 들어 이벤트 중심 패턴에 따라 소비자를 구현하려는 경우 DefaultEndpoint 를 확장하고 createConsumer() 메서드를 구현하여 끝점을 구현합니다. createPollingConsumer() 의 구현은 다음과 같이 정의된 DefaultEndpoint 에서 상속됩니다.

public PollingConsumer<E> createPollingConsumer() throws Exception {
    return new EventDrivenPollingConsumer<E>(this);
}

EventDrivenPollingConsumer 생성자는 이벤트 중심 소비자에 대한 참조를 가져와 효과적으로 래핑하여 폴링 소비자로 변환합니다. 변환을 구현하기 위해 EventDrivenPollingConsumer 인스턴스는 수신 이벤트를 버퍼링하고 필요에 따라 receive(), receive(long timeout)receiveNoWait() 메서드를 통해 사용할 수 있도록 합니다.

마찬가지로 폴링 패턴에 따라 소비자를 구현하는 경우 DefaultPollingEndpoint 를 확장하고 createPollingConsumer() 메서드를 구현하여 끝점을 구현합니다. 이 경우 createConsumer() 메서드의 구현은 DefaultPollingEndpoint 에서 상속되고 기본 구현에서는 DefaultScheduledPollConsumer 인스턴스를 반환합니다 (이는 폴링 소비자를 이벤트 중심 소비자로 변환).

41.1.5. CryostatPrepared 인터페이스

소비자 클래스는 선택적으로 org.apache.camel.spi.ShutdownPrepared 인터페이스를 구현하여 사용자 정의 소비자 엔드포인트에서 종료 알림을 수신할 수 있습니다.

예 41.2. “CryostatPrepared Interface”미리 구문 분석된 인터페이스 의 정의를 표시합니다.

예 41.2. CryostatPrepared Interface

package org.apache.camel.spi;

public interface ShutdownPrepared {

    void prepareShutdown(boolean forced);

}

Cryo statPrepared 인터페이스는 다음 메서드를 정의합니다.

prepareShutdown

다음과 같이 하나 또는 두 단계로 소비자 끝점을 종료하라는 알림을 받습니다.

  1. 강제 인수의 값이 false 인 경우 정상 종료. 리소스를 정상적으로 정리합니다. 예를 들어 스레드를 정상적으로 중지하면 됩니다.
  2. 강제 종료 시 강제 인수의 값이 true 입니다. 즉, 종료 시간이 초과되었으므로 리소스를 더 공격적으로 정리해야 합니다. 프로세스가 종료되기 전에 리소스를 정리할 수 있는 마지막 방법입니다.

41.1.6. CryostatAware 인터페이스

소비자 클래스는 선택 사항으로 정상 종료 메커니즘과 상호 작용하는 org.apache.camel.spi.ShutdownAware 인터페이스를 구현하여 사용자가 종료하는데 추가 시간을 요청할 수 있습니다. 이는 일반적으로 내부 큐에 대기 중인 교환을 저장할 수 있는 SEDA와 같은 구성 요소에 필요합니다. 일반적으로 SEDA 소비자를 종료하기 전에 큐의 모든 교환을 처리하고 싶습니다.

예 41.3. “CryostatAware 인터페이스” 에는 인터페이스 정의가 표시됩니다.

예 41.3. CryostatAware 인터페이스

// Java
package org.apache.camel.spi;

import org.apache.camel.ShutdownRunningTask;

public interface ShutdownAware extends ShutdownPrepared {

    boolean deferShutdown(ShutdownRunningTask shutdownRunningTask);

    int getPendingExchangesSize();
}

Cryo statAware 인터페이스는 다음 방법을 정의합니다.

deferShutdown

소비자 종료를 지연하려면 이 메서드에서 true 를 반환합니다. shutdownRunningTask 인수는 다음 값 중 하나를 사용할 수 있는 enum 입니다.

  • 현재 소비자 의 스레드 풀에서 처리 중인 교환을 처리하지만 그 이상의 교환을 처리하지는 않습니다.
  • CryostatRunningTask.CompleteAllTasks Cryo stat->-<process 모든 보류 중인 거래입니다. 예를 들어, SEDA 구성 요소의 경우 소비자는 들어오는 큐에서 모든 교환을 처리합니다.
getPendingExchangesSize
소비자가 처리할 수 있는 상호 작용 수를 나타냅니다. 0 값은 처리가 완료되고 소비자를 종료할 수 있음을 나타냅니다.

예 41.7. “사용자 정의 스레드 구현”참조하십시오.

41.2. 소비자 인터페이스 구현

41.2.1. 소비자를 구현하는 대체 방법

다음 방법 중 하나로 소비자를 구현할 수 있습니다.

41.2.2. 이벤트 중심 소비자 구현

이벤트 중심 소비자에서 처리는 외부 이벤트에 의해 명시적으로 구동됩니다. 이벤트는 event-listener 인터페이스를 통해 수신되며, 여기서 리스너 인터페이스는 특정 이벤트 소스에 따라 다릅니다.

예 41.4. “CryostatConsumer 구현” Apache Camel Cryo stat 구성 요소 구현에서 가져온 CryostatConsumer 클래스의 구현을 보여줍니다. CryostatConsumer 클래스는 org.apache.camel.impl.DefaultConsumer 클래스에서 상속하여 구현된 이벤트 중심 소비자의 예입니다. Cryostat Consumer 예제 의 경우 이벤트는 Cryostat 이벤트를 수신하는 표준 방법인 NotificationListener.handleNotification() 메서드를 호출하여 표시됩니다. 이러한 Cryostat 이벤트를 수신하려면 예 41.4. “CryostatConsumer 구현” 에 표시된 대로 NotificationListener 인터페이스를 구현하고 handleNotification() 메서드를 재정의해야 합니다.

예 41.4. CryostatConsumer 구현

package org.apache.camel.component.jmx;

import javax.management.Notification;
import javax.management.NotificationListener;
import org.apache.camel.Processor;
import org.apache.camel.impl.DefaultConsumer;

public class JMXConsumer extends DefaultConsumer implements NotificationListener { 1

    JMXEndpoint jmxEndpoint;

    public JMXConsumer(JMXEndpoint endpoint, Processor processor) { 2
        super(endpoint, processor);
        this.jmxEndpoint = endpoint;
    }

    public void handleNotification(Notification notification, Object handback) { 3
        try {
            getProcessor().process(jmxEndpoint.createExchange(notification)); 4
        } catch (Throwable e) {
            handleException(e); 5
        }
    }
}
1
Default Consumer 패턴은 DefaultConsumer 클래스를 확장하여 이벤트 중심 소비자의 일반적인 패턴을 따릅니다. 또한 이 소비자는 Cryostat 알림에서 이벤트를 수신하도록 설계되었으므로 NotificationListener 인터페이스를 구현해야 합니다.
2
상위 끝점, 엔드포인트 및 체인의 다음 프로세서에 대한 참조를 사용하는 하나 이상의 생성자를 인수로 구현해야 합니다.
3
NotificationListener에 정의된 handleNotification() 메서드는 Cryostat 알림이 도달할 때마다 Cryostat에서 자동으로 호출됩니다. 이 메서드의 본문에는 소비자의 이벤트 처리를 수행하는 코드가 포함되어야 합니다. handleNotification() 호출은 Cryostat 계층에서 시작되므로 소비자의 스레드링 모델은 Cryostat 계층이 아닌 Cryostat 계층에서 암시적으로 제어됩니다.
4
이 코드 줄은 두 단계를 결합합니다. 먼저 Cryostat 알림 오브젝트는 Apache Camel에서 이벤트의 일반 표현인 교환 오브젝트로 변환됩니다. 그런 다음 새로 생성된 교환 오브젝트가 경로의 다음 프로세서로 전달됩니다(동시적으로 계산됨).
5
handleException() 메서드는 DefaultConsumer 기본 클래스에서 구현됩니다. 기본적으로 org.apache.camel.impl.LoggingExceptionHandler 클래스를 사용하여 예외를 처리합니다.
참고

handleNotification() 메서드는 Cryostat 예제에 따라 다릅니다. 자체 이벤트 중심 소비자를 구현할 때는 사용자 정의 소비자에 구현할 유사한 이벤트 리스너 메서드를 식별해야 합니다.

41.2.3. 예약된 폴링 소비자 구현

예약된 폴링 소비자에서 폴링 이벤트는 타이머 클래스인 java.util.concurrent.ScheduledExecutorService 에 의해 자동으로 생성됩니다. 생성된 폴링 이벤트를 수신하려면 ScheduledPollConsumer.poll() 메서드를 구현해야 합니다( 38.1.3절. “소비자 패턴 및 스레드”참조).

예 41.5. “ScheduledPollConsumer Implementation” ScheduledPollConsumer 클래스를 확장하여 구현된 예약된 폴링 패턴을 따르는 소비자를 구현하는 방법을 보여줍니다.

예 41.5. ScheduledPollConsumer Implementation

import java.util.concurrent.ScheduledExecutorService;

import org.apache.camel.Consumer;
import org.apache.camel.Endpoint;
import org.apache.camel.Exchange;
import org.apache.camel.Message;
import org.apache.camel.PollingConsumer;
import org.apache.camel.Processor;

import org.apache.camel.impl.ScheduledPollConsumer;

public class pass:quotes[CustomConsumer] extends ScheduledPollConsumer { 1
    private final pass:quotes[CustomEndpoint] endpoint;

    public pass:quotes[CustomConsumer](pass:quotes[CustomEndpoint] endpoint, Processor processor) { 2
        super(endpoint, processor);
        this.endpoint = endpoint;
    }

    protected void poll() throws Exception { 3
        Exchange exchange = /* Receive exchange object ... */;

        // Example of a synchronous processor.
        getProcessor().process(exchange); 4
    }

    @Override
    protected void doStart() throws Exception { 5
        // Pre-Start:
        // Place code here to execute just before start of processing.
        super.doStart();
        // Post-Start:
        // Place code here to execute just after start of processing.
    }

    @Override
    protected void doStop() throws Exception { 6
        // Pre-Stop:
        // Place code here to execute just before processing stops.
        super.doStop();
        // Post-Stop:
        // Place code here to execute just after processing stops.
    }
}
1
org.apache.camel.impl.ScheduledPollConsumer 클래스를 확장하여 예약된 폴링 소비자 클래스인 CustomConsumer 를 구현합니다.
2
상위 끝점, 엔드포인트 및 체인의 다음 프로세서에 대한 참조를 사용하는 하나 이상의 생성자를 인수로 구현해야 합니다.
3
poll() 메서드를 재정의하여 예약된 폴링 이벤트를 수신합니다. 여기에서 들어오는 이벤트를 검색하고 처리하는 코드를 배치해야 합니다(배체 개체에 의해 표시됨).
4
이 예제에서는 이벤트가 동기적으로 처리됩니다. 이벤트를 비동기적으로 처리하려면 getAsyncProcessor() 를 호출하여 비동기 프로세서에 대한 참조를 사용해야 합니다. 이벤트를 비동기적으로 처리하는 방법에 대한 자세한 내용은 38.1.4절. “비동기 처리” 을 참조하십시오.
5
(선택 사항) 소비자가 시작될 때 일부 코드 행을 실행하려면 표시된 대로 doStart() 메서드를 재정의합니다.
6
(선택 사항) 소비자가 중지됨에 따라 일부 코드 행을 실행하려면 표시된 대로 doStop() 메서드를 재정의합니다.

41.2.4. 폴링 소비자 구현

예 41.6. “PollingConsumerSupport 구현” PollingConsumerSupport 클래스를 확장하여 구현되는 폴링 패턴을 따르는 소비자를 구현하는 방법을 간략하게 설명합니다.

예 41.6. PollingConsumerSupport 구현

import org.apache.camel.Exchange;
import org.apache.camel.RuntimeCamelException;
import org.apache.camel.impl.PollingConsumerSupport;

public class pass:quotes[CustomConsumer] extends PollingConsumerSupport { 1
    private final pass:quotes[CustomEndpoint] endpoint;

    public pass:quotes[CustomConsumer](pass:quotes[CustomEndpoint] endpoint) { 2
        super(endpoint);
        this.endpoint = endpoint;
    }

    public Exchange receiveNoWait() { 3
        Exchange exchange = /* Obtain an exchange object. */;
        // Further processing ...
        return exchange;
    }

    public Exchange receive() { 4
        // Blocking poll ...
    }

    public Exchange receive(long timeout) { 5
        // Poll with timeout ...
    }

    protected void doStart() throws Exception { 6
        // Code to execute whilst starting up.
    }

    protected void doStop() throws Exception {
        // Code to execute whilst shutting down.
    }
}
1
org.apache.camel.impl.PollingConsumerSupport 클래스를 확장하여 폴링 소비자 클래스인 CustomConsumer 를 구현합니다.
2
부모 끝점, 엔드포인트에 대한 참조를 인수로 사용하는 하나 이상의 생성자를 구현해야 합니다. 폴링 소비자는 프로세서 인스턴스에 대한 참조가 필요하지 않습니다.
3
receiveNoWait() 메서드는 이벤트를 검색하기 위한 비차단 알고리즘을 구현해야 합니다(exchange 오브젝트). 이벤트를 사용할 수 없는 경우 null 을 반환해야 합니다.
4
receive() 메서드는 이벤트를 검색하기 위한 차단 알고리즘을 구현해야 합니다. 이 방법은 이벤트를 사용할 수 없는 경우 무기한 차단될 수 있습니다.
5
receive(long timeout) 메서드는 지정된 시간 초과(일반적으로 밀리초 단위로 지정됨)로 차단할 수 있는 알고리즘을 구현합니다.
6
소비자가 시작 또는 종료되는 동안 실행되는 코드를 삽입하려면 doStart() 메서드와 doStop() 메서드를 각각 구현합니다.

41.2.5. 사용자 정의 스레드 구현

표준 소비자 패턴이 소비자 구현에 적합하지 않은 경우 소비자 인터페이스를 직접 구현하고 스레드 코드를 직접 작성할 수 있습니다. 그러나 스레드 코드를 작성할 때는 2.8절. “스레드 모델” 에 설명된 대로 표준 Apache Camel 스레딩 모델을 준수하는 것이 중요합니다.

예를 들어 camel-core 의 SEDA 구성 요소는 Apache Camel 스레딩 모델과 일치하는 자체 소비자 스레딩을 구현합니다. 예 41.7. “사용자 정의 스레드 구현” SedaConsumer 클래스에서 스레드를 구현하는 방법에 대한 개요를 보여줍니다.

예 41.7. 사용자 정의 스레드 구현

package org.apache.camel.component.seda;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;

import org.apache.camel.Consumer;
import org.apache.camel.Endpoint;
import org.apache.camel.Exchange;
import org.apache.camel.Processor;
import org.apache.camel.ShutdownRunningTask;
import org.apache.camel.impl.LoggingExceptionHandler;
import org.apache.camel.impl.ServiceSupport;
import org.apache.camel.util.ServiceHelper;
...
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * A Consumer for the SEDA component.
 *
 * @version $Revision: 922485 $
 */
public class SedaConsumer extends ServiceSupport implements Consumer, Runnable, ShutdownAware { 1
    private static final transient Log LOG = LogFactory.getLog(SedaConsumer.class);

    private SedaEndpoint endpoint;
    private Processor processor;
    private ExecutorService executor;
    ...
    public SedaConsumer(SedaEndpoint endpoint, Processor processor) {
        this.endpoint = endpoint;
        this.processor = processor;
    }
    ...

    public void run() { 2
        BlockingQueue<Exchange> queue = endpoint.getQueue();
        // Poll the queue and process exchanges
        ...
    }

    ...
    protected void doStart() throws Exception { 3
        int poolSize = endpoint.getConcurrentConsumers();
        executor = endpoint.getCamelContext().getExecutorServiceStrategy()
            .newFixedThreadPool(this, endpoint.getEndpointUri(), poolSize); 4
        for (int i = 0; i < poolSize; i++) { 5
            executor.execute(this);
        }
        endpoint.onStarted(this);
    }

    protected void doStop() throws Exception { 6
        endpoint.onStopped(this);
        // must shutdown executor on stop to avoid overhead of having them running
        endpoint.getCamelContext().getExecutorServiceStrategy().shutdownNow(executor); 7

        if (multicast != null) {
            ServiceHelper.stopServices(multicast);
        }
    }
    ...
    //----------
    // Implementation of ShutdownAware interface

    public boolean deferShutdown(ShutdownRunningTask shutdownRunningTask) {
        // deny stopping on shutdown as we want seda consumers to run in case some other queues
        // depend on this consumer to run, so it can complete its exchanges
        return true;
    }

    public int getPendingExchangesSize() {
        // number of pending messages on the queue
        return endpoint.getQueue().size();
    }

}
1
SedaConsumer 클래스는 org.apache.camel.impl.ServiceSupport 클래스를 확장하고 Consumer,Runnable 및 Cryostat Aware 인터페이스를 구현하여 구현됩니다.
2
Runnable.run() 메서드를 구현하여 스레드에서 실행되는 동안 소비자가 수행하는 작업을 정의합니다. 이 경우 소비자는 루프에서 실행되며, 새로운 교환을 위해 큐를 폴링한 다음 대기열의 마지막 부분에서 교환을 처리합니다.
3
doStart() 메서드는 ServiceSupport 에서 상속됩니다. 소비자가 시작할 때 수행하는 작업을 정의하기 위해 이 메서드를 재정의합니다.
4
스레드를 직접 생성하는 대신 CamelContext 에 등록된 ExecutorServiceStrategy 오브젝트를 사용하여 스레드 풀을 생성해야 합니다. 이는 Apache Camel에서 스레드의 중앙 집중식 관리 및 정상 종료와 같은 지원을 구현할 수 있기 때문에 중요합니다. 자세한 내용은 2.8절. “스레드 모델”의 내용을 참조하십시오.
5
ExecutorService.execute() 메서드를 poolSize 번 호출하여 스레드를 시작합니다.
6
doStop() 메서드는 ServiceSupport 에서 상속됩니다. 소비자가 종료할 때 수행하는 작업을 정의하기 위해 이 방법을 재정의합니다.
7
executor 인스턴스에 의해 표시되는 스레드 풀을 종료합니다.

42장. 생산자 인터페이스

초록

이 장에서는 Apache Camel 구성 요소를 구현하는 데 중요한 단계인 Producer 인터페이스를 구현하는 방법을 설명합니다.

42.1. Producer 인터페이스

42.1.1. 개요

org.apache.camel.Producer 유형의 인스턴스는 경로의 대상 끝점을 나타냅니다. 생산자의 역할은 요청(메시지에서 )을 특정 물리적 엔드포인트에 전송하고 해당 응답(아웃 또는 Fault 메시지)을 수신하는 것입니다. Producer 오브젝트는 기본적으로 프로세서 체인의 끝에 표시되는 특수 종류의 프로세서입니다(경로와 동일). 그림 42.1. “생산자 Inheritance Hierarchy” 생산자의 상속 계층 구조를 표시합니다.

그림 42.1. 생산자 Inheritance Hierarchy

생산자 상속 계층

42.1.2. Producer 인터페이스

예 42.1. “생산자 인터페이스” org.apache.camel.Producer 인터페이스의 정의를 보여줍니다.

예 42.1. 생산자 인터페이스

package org.apache.camel;

public interface Producer extends Processor, Service, IsSingleton {

    Endpoint<E> getEndpoint();

    Exchange createExchange();

    Exchange createExchange(ExchangePattern pattern);

    Exchange createExchange(E exchange);
}

42.1.3. 생산자 메서드

Producer 인터페이스는 다음 방법을 정의합니다.

  • process()(프로세서에서 상속됨) - 가장 중요한 메서드입니다. 생산자는 기본적으로 교환 오브젝트를 다른 프로세서로 전달하는 대신 엔드포인트에 요청을 전송하는 특수 유형의 프로세서입니다. process() 메서드를 재정의하면 생산자가 관련 엔드포인트로 메시지를 보내고 수신하는 방법을 정의합니다.
  • getEndpoint() Cryostat-WITH parent endpoint 인스턴스에 대한 참조입니다.
  • createExchange() Cryostat-property overloaded 메서드는 Endpoint 인터페이스에 정의된 해당 메서드와 유사합니다. 일반적으로 이러한 메서드는 상위 끝점 인스턴스에 정의된 해당 메서드에 위임됩니다(기본적으로 DefaultEndpoint 클래스가 수행하는 사항임). 이러한 방법을 재정의해야 하는 경우도 있습니다.

42.1.4. 비동기 처리

프로듀서에서 교환 오브젝트를 처리하는 경우 일반적으로 메시지를 원격 대상으로 전송하고 response Cryostat- Cryostatcan을 기다리는 작업이 상당한 시간 동안 차단될 수 있습니다. 현재 스레드를 차단하지 않으려면 생산자를 비동기 프로세서 로 구현하도록 선택할 수 있습니다. 비동기 처리 패턴은 이전 프로세서를 생산자와 분리하여 process() 메서드가 지연 없이 반환되도록 합니다. 38.1.4절. “비동기 처리”을 참조하십시오.

생산자를 구현할 때 org.apache.camel.AsyncProcessor 인터페이스를 구현하여 비동기 처리 모델을 지원할 수 있습니다. 그 자체로는 비동기 처리 모델이 사용되는지 확인하는 것만으로는 충분하지 않습니다. 체인의 이전 프로세서가 process() 메서드의 비동기 버전을 호출하는 것도 필요합니다. AsyncProcessor 인터페이스의 정의는 예 42.2. “AsyncProcessor 인터페이스” 에 표시됩니다.

예 42.2. AsyncProcessor 인터페이스

package org.apache.camel;

public interface AsyncProcessor extends Processor {
    boolean process(Exchange exchange, AsyncCallback callback);
}

process() 메서드의 비동기 버전은 org.apache.camel.AsyncCallback 유형의 추가 인수인 콜백 을 사용합니다. 해당 AsyncCallback 인터페이스는 예 42.3. “AsyncCallback 인터페이스” 에 표시된 대로 정의됩니다.

예 42.3. AsyncCallback 인터페이스

package org.apache.camel;

public interface AsyncCallback {
    void done(boolean doneSynchronously);
}

AsyncProcessor.process() 의 호출자는 처리가 완료되었다는 알림을 수신하기 위해 AsyncCallback의 구현을 제공해야 합니다. AsyncCallback.done() 메서드는 처리가 동기적으로 수행되었는지 여부를 나타내는 부울 인수를 사용합니다. 일반적으로 플래그는 비동기 처리를 나타내는 false 입니다. 그러나 경우에 따라 생산자가 비동기적으로 처리되지 않는 것이 적절할 수 있습니다(요청을 받는 경우). 예를 들어 생산자가 교환 처리가 빠르게 완료된다는 것을 알고 있으면 동기적으로 처리를 수행하여 처리를 최적화할 수 있습니다. 이 경우 doneSynchronously 플래그를 true 로 설정해야 합니다.

42.1.5. ExchangeHelper 클래스

프로듀서를 구현할 때 org.apache.camel.util.ExchangeHelper 유틸리티 클래스에서 일부 메서드를 호출하는 것이 도움이 될 수 있습니다. ExchangeHelper 클래스에 대한 자세한 내용은 35.4절. “ExchangeHelper 클래스” 을 참조하십시오.

42.2. Producer 인터페이스 구현

42.2.1. 생산자를 구현하는 다른 방법

다음 방법 중 하나로 생산자를 구현할 수 있습니다.

42.2.2. 동기 생산자를 구현하는 방법

예 42.4. “DefaultProducer 구현” 동기 생산자를 구현하는 방법을 간략하게 설명합니다. 이 경우 응답을 수신할 때까지 Producer.process() 블록을 호출합니다.

예 42.4. DefaultProducer 구현

import org.apache.camel.Endpoint;
import org.apache.camel.Exchange;
import org.apache.camel.Producer;
import org.apache.camel.impl.DefaultProducer;

public class CustomProducer extends DefaultProducer { 1

    public CustomProducer(Endpoint endpoint) { 2
        super(endpoint);
        // Perform other initialization tasks...
    }

    public void process(Exchange exchange) throws Exception { 3
        // Process exchange synchronously.
        // ...
    }
}
1
org.apache.camel.impl.DefaultProducer 클래스를 확장하여 사용자 정의 동기 생산자 클래스인 CustomProducer 를 구현합니다.
2
상위 끝점에 대한 참조를 사용하는 생성자를 구현합니다.
3
process() 메서드 구현은 생산자 코드의 코어를 나타냅니다. process() 메서드의 구현은 구현 중인 구성 요소의 유형에 따라 전적으로 달라집니다.

개요에서 process() 메서드는 일반적으로 다음과 같이 구현됩니다.

  • 교환에 In 메시지가 포함되어 있고 지정된 교환 패턴과 일치하는 경우 In 메시지를 지정된 엔드포인트로 보냅니다.
  • 교환 패턴에서 Out 메시지를 수신할 것으로 예상되는 경우 Out 메시지가 수신될 때까지 기다립니다. 이 경우 process() 메서드가 상당한 시간 동안 차단됩니다.
  • 응답이 수신되면 exchange.setOut() 을 호출하여 응답을 교환 오브젝트에 연결합니다. 응답에 fault 메시지가 포함된 경우 Message.setFault(true) 를 사용하여 Out 메시지의 fault 플래그를 설정합니다.

42.2.3. 비동기 생산자 구현 방법

예 42.5. “CollectionProducer 구현” 비동기 생산자를 구현하는 방법을 간략하게 설명합니다. 이 경우 동기 프로세스() 메서드와 비동기 프로세스() 메서드를 모두 구현해야 합니다(추가 AsyncCallback 인수를 사용합니다).

예 42.5. CollectionProducer 구현

import org.apache.camel.AsyncCallback;
import org.apache.camel.AsyncProcessor;
import org.apache.camel.Endpoint;
import org.apache.camel.Exchange;
import org.apache.camel.Producer;
import org.apache.camel.impl.DefaultProducer;

public class _CustomProducer_ extends DefaultProducer implements AsyncProcessor { 1

    public _CustomProducer_(Endpoint endpoint) { 2
        super(endpoint);
        // ...
    }

    public void process(Exchange exchange) throws Exception { 3
        // Process exchange synchronously.
        // ...
    }

    public boolean process(Exchange exchange, AsyncCallback callback) { 4
        // Process exchange asynchronously.
        CustomProducerTask task = new CustomProducerTask(exchange, callback);
        // Process 'task' in a separate thread...
        // ...
        return false; 5
    }
}

public class CustomProducerTask implements Runnable { 6
    private Exchange exchange;
    private AsyncCallback callback;

    public CustomProducerTask(Exchange exchange, AsyncCallback callback) {
        this.exchange = exchange;
        this.callback = callback;
    }

    public void run() { 7
        // Process exchange.
        // ...
        callback.done(false);
    }
}
1
org.apache.camel.impl.DefaultProducer 클래스를 확장하고 AsyncProcessor 인터페이스를 구현하여 사용자 지정 비동기 생산자 클래스인 CustomProducer 를 구현합니다.
2
상위 끝점에 대한 참조를 사용하는 생성자를 구현합니다.
3
동기 프로세스() 메서드를 구현합니다.
4
비동기 프로세스() 메서드를 구현합니다. 비동기 메서드를 여러 가지 방법으로 구현할 수 있습니다. 여기에 표시된 접근 방식은 하위 스레드에서 실행되는 코드를 나타내는 java.lang.Runnable 인스턴스인 task 를 생성하는 것입니다. 그런 다음 Java 스레딩 API를 사용하여 하위 스레드에서 작업을 실행합니다(예: 새 스레드를 생성하거나 기존 스레드 풀에 작업을 할당하여).
5
일반적으로 비동기 프로세스() 메서드에서 false 를 반환하여 교환이 비동기적으로 처리되었음을 나타냅니다.
6
CustomProducerTask 클래스는 하위 스레드에서 실행되는 처리 코드를 캡슐화합니다. 이 클래스는 Exchange 개체의 복사본, 교환AsyncCallback 개체, 콜백 을 프라이빗 멤버 변수로 저장해야 합니다.
7
run() 메서드에는 In 메시지를 생산자 엔드포인트에 전송하고 응답을 수신할 때까지 대기하는 코드가 포함되어 있습니다. 응답(Out message 또는 Fault message)을 수신하고 이를 교환 오브젝트에 삽입한 후 callback.done() 을 호출하여 호출자에게 처리가 완료되었음을 알려야 합니다.

43장. 교환 인터페이스

초록

이 장에서는 교환 인터페이스에 대해 설명합니다. Apache Camel 2.0에서 수행되는 camel-core 모듈 리팩토링은 더 이상 사용자 정의 교환 유형을 정의할 필요가 없습니다. 이제 DefaultExchange 구현을 모든 경우에 사용할 수 있습니다.

43.1. 교환 인터페이스

43.1.1. 개요

org.apache.camel.Exchange 유형의 인스턴스는 경로를 통과하는 현재 메시지를 캡슐화하며, 교환 속성으로 인코딩되는 추가 메타데이터를 캡슐화합니다.

그림 43.1. “Exchange Inheritance Hierarchy” 교환 유형에 대한 상속 계층 구조를 표시합니다. 기본 구현인 DefaultExchange 가 항상 사용됩니다.

그림 43.1. Exchange Inheritance Hierarchy

상속 계층 교환

43.1.2. 교환 인터페이스

예 43.1. “교환 인터페이스” org.apache.camel.Exchange 인터페이스의 정의를 보여줍니다.

예 43.1. 교환 인터페이스

package org.apache.camel;

import java.util.Map;

import org.apache.camel.spi.Synchronization;
import org.apache.camel.spi.UnitOfWork;

public interface Exchange {
    // Exchange property names (string constants)
    // (Not shown here)
    ...

    ExchangePattern getPattern();
    void setPattern(ExchangePattern pattern);

    Object getProperty(String name);
    Object getProperty(String name, Object defaultValue);
    <T> T  getProperty(String name, Class<T> type);
    <T> T  getProperty(String name, Object defaultValue, Class<T> type);
    void   setProperty(String name, Object value);
    Object removeProperty(String name);
    Map<String, Object> getProperties();
    boolean hasProperties();

    Message getIn();
    <T> T   getIn(Class<T> type);
    void    setIn(Message in);

    Message getOut();
    <T> T   getOut(Class<T> type);
    void    setOut(Message out);
    boolean hasOut();

    Throwable getException();
    <T> T     getException(Class<T> type);
    void      setException(Throwable e);

    boolean isFailed();

    boolean isTransacted();

    boolean isRollbackOnly();

    CamelContext getContext();

    Exchange copy();

    Endpoint getFromEndpoint();
    void     setFromEndpoint(Endpoint fromEndpoint);

    String getFromRouteId();
    void   setFromRouteId(String fromRouteId);

    UnitOfWork getUnitOfWork();
    void setUnitOfWork(UnitOfWork unitOfWork);

    String getExchangeId();
    void setExchangeId(String id);

    void addOnCompletion(Synchronization onCompletion);
    void handoverCompletions(Exchange target);
}

43.1.3. 교환 방법

교환 인터페이스는 다음 방법을 정의합니다.

  • getPattern(), setPattern() Cryostat-2307-change 패턴은 org.apache.camel.ExchangePattern 에 열거된 값 중 하나일 수 있습니다. 다음과 같은 교환 패턴 값이 지원됩니다.

    • InOnly
    • RobustInOnly
    • InOut
    • InOptionalOut
    • OutOnly
    • RobustOutOnly
    • OutIn
    • OutOptionalIn
  • SetProperty(), getProperty(), getProperties(), removeProperty(), hasProperties() Cryostat- Cryostat 속성 setter 및 getter 메서드를 사용하여 이름이 지정된 속성을 교환 인스턴스와 연결합니다. 속성은 구성 요소 구현에 필요할 수 있는 기타 메타데이터로 구성됩니다.
  • SetIn(), getIn(), getIn() ECDSASetter 및 getter 메서드의 In 메시지입니다.

    DefaultExchange 클래스에서 제공하는 getIn() 구현은 지연 생성 의미 체계를 구현합니다. get In () 이 호출되면 In 메시지가 null이면 DefaultExchange 클래스는 기본 In 메시지를 생성합니다.

  • SetOut(), getOut(), hasOut() Cryostat- CryostatSetter and getter methods for the Out message.

    getOut() 메서드는 Out 메시지의 지연 생성을 암시적으로 지원합니다. 즉, 현재 Out 메시지가 null 이면 새 메시지 인스턴스가 자동으로 생성됩니다.

  • setException(), getException() Cryostat-cidrGetter 및 setter 메서드( Throwable 유형)에 대한 속성입니다.
  • isFailed() Cryostat- 마이그레이션에서 예외로 인해 또는 오류로 인해 교환이 실패한 경우 true 입니다.
  • 는 exchange가 거래되는 경우 true 입니다.
  • isRollback() Cryostat-이자 return true, 교환이 롤백을 위해 표시된 경우 true입니다.
  • getContext() Cryostat- Cryostat 관련 CamelContext 인스턴스에 대한 참조입니다.
  • 현재 사용자 지정 교환 개체의 동일한 새 복사본 을 만듭니다.Creates a new, identical (apart from the exchange ID) copy of the current custom exchange object. In 메시지의 본문 및 헤더, Out 메시지(있는 경우) 및 Fault 메시지(있는 경우)도 이 작업에 의해 복사됩니다.
  • setFromEndpoint(), getFromEndpoint() Cryostat- CryostatGetter 및 setter 메서드(일반적으로 경로 시작 시 from() DSL 명령에 나타나는 끝점)가 조직된 소비자 끝점에 대한 설정 메서드입니다.
  • setFromRouteId(), getFromRouteId() Cryostat- CryostatGetECDSA 및 이 교환을 시작한 경로 ID에 대해 zone을 설정합니다. getFromRouteId() 메서드는 내부적으로만 호출해야 합니다.
  • setUnitOfWork(), getUnitOfWork() Cryostat-ECDHEGetter 및 setter 메서드 org.apache.camel.spi.UnitOfWork VLAN 속성. 이 속성은 트랜잭션에 참여할 수 있는 교환에만 필요합니다.
  • setExchangeId(), getExchangeId() Cryostat- CryostatGetter 및 교환 ID에 대한 setter 메서드. 사용자 지정 구성 요소에서 교환 ID를 사용하는지 여부는 구현 세부 정보입니다.
  • addOnCompletion() Cryostat- CryostatAdds an org.apache.camel.spi.Synchronization callback object, which is called when processing of the exchange has completed.
  • 지정된 교환 개체에 대한 모든 OnCompletion 콜백 오브젝트를 통해 handoverCompletions() 입니다.

44장. 메시지 인터페이스

초록

이 장에서는 Apache Camel 구성 요소를 구현하는 선택적 단계인 Message 인터페이스를 구현하는 방법을 설명합니다.

44.1. 메시지 인터페이스

44.1.1. 개요

org.apache.camel.Message 유형의 인스턴스는 모든 종류의 메시지(in 또는 Out)를 나타낼 수 있습니다. 그림 44.1. “메시지 상속 계층 구조” 메시지 유형의 상속 계층 구조를 표시합니다. 구성 요소에 대한 사용자 지정 메시지 유형을 항상 구현할 필요는 없습니다. 대부분의 경우 기본 구현인 DefaultMessage 가 적합합니다.

그림 44.1. 메시지 상속 계층 구조

메시지 상속 계층

44.1.2. 메시지 인터페이스

예 44.1. “메시지 인터페이스” org.apache.camel.Message 인터페이스의 정의를 보여줍니다.

예 44.1. 메시지 인터페이스

package org.apache.camel;

import java.util.Map;
import java.util.Set;

import javax.activation.DataHandler;

public interface Message {

    String getMessageId();
    void setMessageId(String messageId);

    Exchange getExchange();

    boolean isFault();
    void    setFault(boolean fault);

    Object getHeader(String name);
    Object getHeader(String name, Object defaultValue);
    <T> T getHeader(String name, Class<T> type);
    <T> T getHeader(String name, Object defaultValue, Class<T> type);
    Map<String, Object> getHeaders();
    void setHeader(String name, Object value);
    void setHeaders(Map<String, Object> headers);
    Object  removeHeader(String name);
    boolean removeHeaders(String pattern);
    boolean hasHeaders();

    Object getBody();
    Object getMandatoryBody() throws InvalidPayloadException;
    <T> T  getBody(Class<T> type);
    <T> T  getMandatoryBody(Class<T> type) throws InvalidPayloadException;
    void     setBody(Object body);
    <T> void setBody(Object body, Class<T> type);

    DataHandler getAttachment(String id);
    Map<String, DataHandler> getAttachments();
    Set<String> getAttachmentNames();
    void removeAttachment(String id);
    void addAttachment(String id, DataHandler content);
    void setAttachments(Map<String, DataHandler> attachments);
    boolean hasAttachments();

    Message copy();

    void copyFrom(Message message);

    String createExchangeId();
}

44.1.3. 메시지 방법

Message 인터페이스는 다음 메서드를 정의합니다.

  • setMessageId(), getMessageId() Cryostat- CryostatGetter 및 메시지 ID에 대한 setter 메서드. 사용자 지정 구성 요소에서 메시지 ID를 사용해야 하는지 여부는 구현 세부 정보입니다.
  • getExchange() Cryostat - parent exchange 객체에 대한 참조입니다.
  • isFault(), setFault() Cryostat-ECDHEGetter 및 setter 메서드(이 메시지가 오류 메시지인지 여부를 나타내는 오류 플래그) 및 setter 메서드입니다.
  • getHeader(), getHeaders(), setHeaders(), setHeaders(), removeHeader(), hasHeaders(), message headers에 대한Headers() 및 setter 메서드를 포함합니다. 일반적으로 이러한 메시지 헤더는 실제 헤더 데이터를 저장하거나 기타 메타데이터를 저장하는 데 사용할 수 있습니다.
  • getBody(), getMandatoryBody(), setBody() Cryostat- Cryostat-Getter 및 메시지 본문에 대한 setter 메서드. getMandatoryBody() 접근자는 반환된 본문이 null이 아님을 보장합니다. 그렇지 않으면 InvalidPayloadException 예외가 발생합니다.
  • getAttachment(), getAttachments(), getAttachmentNames(), removeAttachment(), addAttachment(), setAttachment() , hasAttachments(), hasAttachments() Cryostat- CryostatMethods to get, set, add, and remove attachments.
  • 현재 사용자 지정 메시지 개체의 동일한 새 복사본 을 만듭니다.Creates a new, identical (including the message ID) copy of the current custom message object.
  • copyFrom() - Cryostat: 지정된 일반 메시지 개체의 전체 콘텐츠(메시지 ID 포함)를 현재 메시지 인스턴스로 복사합니다. 이 메서드는 메시지 유형에서 복사할 수 있어야 하므로 사용자 지정 속성이 아닌 일반 메시지 속성을 복사합니다.Because this method must be able to copy from any message type, it copies the generic message properties, but not the custom properties.
  • 메시지 구현이 ID  제공할 수 있는 경우 이 교환에 대한 고유 ID를 반환하고, 그렇지 않으면 null 을 반환합니다.

44.2. 메시지 인터페이스 구현

44.2.1. 사용자 정의 메시지 구현 방법

예 44.2. “사용자 정의 메시지 구현” DefaultMessage 클래스를 확장하여 메시지를 구현하는 방법을 간략하게 설명합니다.

예 44.2. 사용자 정의 메시지 구현

import org.apache.camel.Exchange;
import org.apache.camel.impl.DefaultMessage;

public class CustomMessage extends DefaultMessage { 1

    public CustomMessage() { 2
        // Create message with default properties...
    }

    @Override
    public String toString() { 3
        // Return a stringified message...
    }

    @Override
    public CustomMessage newInstance() { 4
        return new CustomMessage( ... );
    }

    @Override
    protected Object createBody() { 5
        // Return message body (lazy creation).
    }

    @Override
    protected void populateInitialHeaders(Map&lt;String, Object&gt; map) { 6
        // Initialize headers from underlying message (lazy creation).
    }

    @Override
    protected void populateInitialAttachments(Map&lt;String, DataHandler&gt; map) { 7
        // Initialize attachments from underlying message (lazy creation).
    }
}
1
org.apache.camel.impl.DefaultMessage 클래스를 확장하여 사용자 정의 메시지 클래스인 CustomMessage 를 구현합니다.
2
일반적으로 기본 속성이 있는 메시지를 생성하는 기본 생성자가 필요합니다.
3
메시지 문자열을 사용자 지정하려면 toString() 메서드를 재정의합니다.
4
newInstance() 메서드는 MessageSupport.copy() 메서드 내부에서 호출됩니다. newInstance() 메서드의 사용자 지정은 현재 메시지 인스턴스의 모든 사용자 지정 속성을 새 메시지 인스턴스로 복사하는 데 중점을 두어야 합니다. MessageSupport.copy() 메서드는 copyFrom() 을 호출하여 일반 메시지 속성을 복사합니다.
5
createBody() 메서드는 MessageSupport.getBody() 메서드와 함께 작동하여 메시지 본문에 대한 지연 액세스를 구현합니다. 기본적으로 메시지 본문은 null 입니다. 이는 애플리케이션 코드가 ( getBody()() 호출) 본문에 액세스하려고 할 때만 본문을 생성해야 합니다. MessageSupport.getBody() 는 메시지 본문에 처음 액세스하면 createBody() 를 자동으로 호출합니다.
6
populateInitialHeaders() 메서드는 헤더 getter 및 setter 메서드와 함께 작동하여 메시지 헤더에 대한 지연 액세스를 구현합니다. 이 메서드는 메시지를 구문 분석하여 메시지 헤더를 추출하고 해시 맵에 삽입합니다. 사용자가 처음으로 헤더(또는 헤더)에 액세스하려고 할 때( getHeaders(), getHeaders(), setHeaders()또는 setHeaders() 를 호출하여) populateInitialHeaders() 메서드가 자동으로 호출됩니다.
7
populateInitialAttachments() 메서드는 attachment getter 및 setter 방법과 함께 작동하여 첨부 파일에 대한 지연 액세스를 구현합니다. 이 방법은 메시지 첨부 파일을 추출하여 해시 맵에 삽입합니다. populateInitialAttachments() 메서드는 사용자가 getAttachment(), getAttachments() , getAttachmentNames () 또는 addAttachment() 를 호출하여 처음으로 첨부(또는 첨부 파일)에 액세스하려고 할 때 자동으로 호출됩니다.

IV 부. API 구성 요소 프레임워크

API Component Framework를 사용하여 Java API를 래핑하는 Camel 구성 요소를 생성하는 방법.

45장. API 구성 요소 프레임워크 소개

초록

API 구성 요소 프레임워크는 대규모 Java API를 기반으로 복잡한 Camel 구성 요소를 구현하는 데 도움이 됩니다.

45.1. API 구성 요소 프레임워크란 무엇입니까?

45.1.1. 동기

옵션이 적은 구성 요소의 경우 구성 요소 구현에 대한 표준 접근 방식은 매우 효과적입니다.38장. 구성 요소 구현 그러나 문제가 되기 시작하는 위치는 많은 수의 옵션으로 구성 요소를 구현해야 하는 경우입니다. 이 문제는 엔터프라이즈급 구성 요소와 관련하여 급격하게 발생하므로 수백 개의 작업으로 구성된 API를 래핑해야 할 수 있습니다. 이러한 구성 요소는 생성 및 유지 관리를 위해 많은 노력이 필요합니다.

API 구성 요소 프레임워크는 이러한 구성 요소를 구현하는 문제를 처리하기 위해 정확하게 개발되었습니다.

45.1.2. API를 구성 요소로 전환

Java API를 기반으로 Camel 구성 요소를 구현하는 경험을 통해 많은 작업이 일상적이고 기계적임을 알 수 있습니다. 특정 Java 메서드를 가져와서 특정 URI 구문에 매핑하며 사용자가 URI 옵션을 통해 메서드 매개 변수를 설정할 수 있도록 하는 것으로 구성됩니다. 이러한 유형의 작업은 자동화 및 코드 생성에 대한 명확한 후보입니다.

45.1.3. 일반 URI 형식

Java API 구현을 자동화하는 첫 번째 단계는 API 메서드를 URI에 매핑하는 표준 방법을 설계하는 것입니다. 이를 위해 모든 Java API를 래핑하는 데 사용할 수 있는 일반 URI 형식을 정의해야 합니다. 따라서 API 구성 요소 프레임워크는 끝점 URI에 대해 다음 구문을 정의합니다.

scheme://endpoint-prefix/endpoint?Option1=Value1&...&OptionN=ValueN

스키마 는 구성 요소에서 정의한 기본 URI 체계입니다. endpoint-prefix 는 래핑된 Java API의 클래스 또는 인터페이스에 매핑되는 짧은 API 이름이며 엔드포인트 는 메서드 이름에 매핑되고 URI 옵션은 메서드 인수 이름에 매핑됩니다.

45.1.4. 단일 API 클래스의 URI 형식

API가 단일 Java 클래스로 구성된 경우 URI의 엔드포인트-접 두사 부분이 중복되고 다음과 같이 URI를 더 짧은 형식으로 지정할 수 있습니다.

scheme://endpoint?Option1=Value1&...&OptionN=ValueN
참고

이 URI 형식을 활성화하려면 구성 요소 구현자가 API 구성 요소 Maven 플러그인 구성에 apiName 요소를 비워 둘 수도 있어야 합니다. 자세한 내용은 “API 매핑 구성” 섹션을 참조하십시오.

45.1.5. 리플렉션 및 메타데이터

Java 메서드 호출을 URI 구문에 매핑하려면 일부 형태의 반영 메커니즘이 필요합니다. 그러나 표준 Java 리플렉션 API는 주목할 만한 제한으로 어려움을 겪습니다: 메서드 인수 이름을 유지하지 않습니다. 의미 있는 URI 옵션 이름을 생성하기 위해 메서드 인수 이름이 필요하기 때문에 문제가 있습니다. 해결 방법은 다른 형식의 메타데이터를 Javadoc 또는 메서드 서명 파일로 제공하는 것입니다.

45.1.6. Javadoc

Javadoc은 메서드 인수 이름을 포함하여 전체 메서드 서명을 유지하기 때문에 API 구성 요소 프레임워크에 이상적인 형식의 메타데이터입니다. 또한 쉽게 생성( maven-javadoc-plugin을 사용하여) 생성이 가능하며, 대부분의 경우 타사 라이브러리에서 이미 제공됩니다.

45.1.7. 메서드 서명 파일

어떤 이유로든 Javadoc을 사용할 수 없거나 적합하지 않은 경우 API 구성 요소 프레임워크는 메서드 서명 파일의 대체 소스도 지원합니다. 서명 파일은 Java 메서드 서명 목록으로 구성된 간단한 텍스트 파일입니다. Java 코드에서 복사 및 붙여넣기를 통해 이러한 파일을 수동으로 생성하는 것은 비교적 쉽습니다(및 결과 파일을 간단히 편집).

45.1.8. 프레임워크는 어떻게 구성됩니까?

구성 요소 개발자의 관점에서 API 구성 요소 프레임워크는 다음과 같이 다양한 요소로 구성됩니다.

Maven archetype
camel-archetype-api-component Maven archetype은 구성 요소 구현에 대한 스keleton 코드를 생성하는 데 사용됩니다.
Maven 플러그인
camel-api-component-maven-plugin Maven 플러그인은 Java API와 끝점 URI 구문 간의 매핑을 구현하는 코드를 생성합니다.
특수 기본 클래스
API 구성 요소 프레임워크의 프로그래밍 모델을 지원하기 위해 Apache Camel 코어는 org.apache.camel.util.component 패키지에 특수 API를 제공합니다. 그 외에도 이 API는 구성 요소, 엔드포인트, 소비자 및 생산자 클래스에 대한 특수 기본 클래스를 제공합니다.

45.2. 프레임워크 사용 방법

45.2.1. 개요

API 프레임워크를 사용하여 구성 요소를 구현하는 절차에는 자동화된 코드 생성이 혼합되어 Java 코드를 구현하고, Maven POM 파일을 편집하여 빌드를 사용자 정의하는 작업이 포함됩니다. 다음 그림은 이 개발 프로세스에 대한 개요를 제공합니다.

그림 45.1. API 구성 요소 프레임워크 사용

API 구성 요소 구현의 일부를 보여주는 그림

45.2.2. Java API

API 구성 요소의 시작점은 항상 Java API입니다. 일반적으로 Camel의 컨텍스트에서는 일반적으로 원격 서버 엔드포인트에 연결하는 Java 클라이언트 API를 의미합니다. 첫 번째 질문은 Java API가 어디에서 발생합니까? 다음은 몇 가지 옵션입니다.

  • Java API를 직접 구현합니다(일반적으로 많은 작업이 필요하며 일반적으로 권장되는 접근 방식은 아닙니다).
  • 타사 Java API를 사용합니다. 예를 들어 Apache Camel Box 구성 요소는 타사 Box Java SDK 라이브러리를 기반으로 합니다.
  • 언어 중립 인터페이스에서 Java API를 생성합니다.

45.2.3. Javadoc 메타데이터

Javadoc 형태로 Java API에 대한 메타데이터를 제공하는 옵션이 있습니다(API 구성 요소 프레임워크에서 코드를 생성하는 데 필요합니다). Maven 리포지토리에서 타사 Java API를 사용하는 경우 일반적으로 Javadoc이 Maven 아티팩트에 이미 제공되어 있음을 알 수 있습니다. 그러나 Javadoc이 제공되지 않는 경우에도 maven-javadoc-plugin Maven 플러그인을 사용하여 쉽게 생성할 수 있습니다.

참고

현재 일반 중첩이 지원되지 않도록 Javadoc 메타데이터 처리에 제한이 있습니다. 예를 들어 java.util.List<String >이 지원되지만 java.util.List<java.util.List<String&gt;>는 지원되지 않습니다. 해결방법은 중첩된 일반 유형을 서명 파일에서 java.util.List<java.util.List >로 지정하는 것입니다.

45.2.4. 서명 파일 메타데이터

어떤 이유로 Java API 메타데이터를 Javadoc 형식으로 제공하는 것이 편리하지 않으면 서명 파일 형식으로 메타데이터를 제공할 수 있습니다. 서명 파일은 메서드 서명 목록(행당 하나의 메서드 서명)으로 구성됩니다. 이러한 파일은 수동으로 생성할 수 있으며 빌드 시에만 필요합니다.

다음에서는 서명 파일에 대해 설명합니다.

  • 각 프록시 클래스(Java API 클래스)에 대해 하나의 서명 파일을 생성해야 합니다.
  • 메서드 서명에서 예외를 throw 해서는 안 됩니다. 런타임 시 발생하는 모든 예외는 RuntimeCamelException 으로 래핑되고 끝점에서 반환됩니다.
  • 인수 유형을 지정하는 클래스 이름은 정규화된 클래스 이름이어야 합니다(Java .lang.\* 유형 제외). 패키지 이름을 가져오는 메커니즘은 없습니다.
  • 현재 서명 구문 분석기에는 일반 중첩이 지원되지 않도록 제한 사항이 있습니다. 예를 들어 java.util.List<String >이 지원되지만 java.util.List<java.util.List<String&gt;>는 지원되지 않습니다. 해결방법은 중첩된 일반 유형을 java.util.List< java.util.List>로 지정하는 것입니다.

다음은 서명 파일의 간단한 예제를 보여줍니다.

public String sayHi();
public String greetMe(String name);
public String greetUs(String name1, String name2);

45.2.5. Maven archetype을 사용하여 시작 코드 생성

API 구성 요소 개발을 시작하는 가장 쉬운 방법은 camel-archetype-api-component Maven archetype을 사용하여 초기 Maven 프로젝트를 생성하는 것입니다. archetype을 실행하는 방법에 대한 자세한 내용은 46.1절. “Maven Archetype을 사용하여 코드 생성” 을 참조하십시오.

Maven archetype을 실행하면 생성된 ProjectName 디렉터리에 두 개의 하위 프로젝트가 있습니다.

ProjectName-api
이 프로젝트에는 API 구성 요소의 기반을 형성하는 Java API가 포함되어 있습니다. 이 프로젝트를 빌드할 때 Maven 번들에 Java API를 패키지하고 필수 Javadoc도 생성합니다. 그러나 Java API 및 Javadoc이 타사에서 이미 제공되어 있지만 이 하위 프로젝트가 필요하지 않습니다.
ProjectName-component
이 프로젝트에는 API 구성 요소의 스케일톤 코드가 포함되어 있습니다.

45.2.6. 구성 요소 클래스 편집

ProjectName-component 에서 스케일톤 코드를 편집하여 고유한 구성 요소 구현을 개발할 수 있습니다. 다음과 같은 생성된 클래스는 스케일톤 구현의 핵심을 구성합니다.

ComponentNameComponent
ComponentNameEndpoint
ComponentNameConsumer
ComponentNameProducer
ComponentNameConfiguration

45.2.7. POM 파일 사용자 정의

또한 Maven POM 파일을 편집하여 빌드를 사용자 지정하고 camel-api-component-maven-plugin Maven 플러그인을 구성해야 합니다.

45.2.8. camel-api-component-maven-plugin 구성

POM 파일을 구성하는 가장 중요한 측면은 camel-api-component-maven-plugin Maven 플러그인의 구성입니다. 이 플러그인은 API 메서드와 끝점 URI 간 매핑을 생성하고 플러그인 구성을 편집하여 매핑을 사용자 지정할 수 있습니다.

예를 들어 ProjectName-component/pom.xml 파일에서 다음 camel-api-component-maven-plugin 플러그인 구성은 ExampleJavadocHello 라는 API 클래스에 대한 최소 구성을 보여줍니다.

<configuration>
  <apis>
    <api>
      <apiName>hello-javadoc</apiName>
      <proxyClass>org.jboss.fuse.example.api.ExampleJavadocHello</proxyClass>
      <fromJavadoc/>
    </api>
  </apis>
</configuration>

이 예제에서 hello-javadoc API 이름은 ExampleJavadocHello 클래스에 매핑됩니다. 즉, 양식의 URI를 사용하여 이 클래스에서 메서드를 호출할 수 있습니다. 스키마://hello-javadoc/끝점. fromJavadoc 요소의 존재는 ExampleJavadocHello 클래스가 Javadoc에서 메타데이터를 가져오는 것을 나타냅니다.

45.2.9. OSGi 번들 구성

구성 요소 하위 프로젝트의 샘플 POM, ProjectName-component/pom.xml 은 구성 요소를 OSGi 번들로 패키징하도록 구성되어 있습니다. 구성 요소 POM에는 maven-bundle-plugin 의 샘플 구성이 포함되어 있습니다. Maven이 구성 요소에 맞게 올바르게 구성된 OSGi 번들을 생성하도록 maven-bundle-plugin 플러그인의 구성을 사용자 지정해야 합니다.

45.2.10. 구성 요소 빌드

Maven(예: mvn clean package을 사용하여) 구성 요소를 빌드할 때 camel-api-component-maven-plugin 플러그인은 API 매핑 클래스(Java API와 엔드포인트 URI 구문 간의 매핑을 정의함)를 자동으로 생성하며 대상/클래스 프로젝트 하위 디렉터리에 배치합니다. 크고 복잡한 Java API를 처리할 때 이 생성된 코드는 실제로 많은 구성 요소 소스 코드를 구성합니다.

Maven 빌드가 완료되면 컴파일된 코드와 리소스는 OSGi 번들로 패키지화되어 로컬 Maven 리포지토리에 Maven 아티팩트로 저장됩니다.

46장. 프레임워크 시작하기

초록

이 장에서는 camel-archetype-api-component Maven archetype을 사용하여 생성된 코드를 기반으로 API 구성 요소 프레임워크를 사용하여 Camel 구성 요소를 구현하는 기본 원칙을 설명합니다.

46.1. Maven Archetype을 사용하여 코드 생성

46.1.1. Maven archetypes

Maven archetype은 코드 마법사와 유사합니다. 몇 가지 간단한 매개 변수가 지정되면 전체 작동 Maven 프로젝트를 생성하고 샘플 코드로 채워집니다. 그런 다음 이 프로젝트를 템플릿으로 사용하여 구현을 사용자 지정하여 자체 애플리케이션을 생성할 수 있습니다.

46.1.2. API 구성 요소 Maven archetype

API 구성 요소 프레임워크는 고유한 API 구성 요소 구현을 위한 시작점 코드를 생성할 수 있는 Maven archetype, camel-archetype-api-component 를 제공합니다. 이 방법은 고유한 API 구성 요소 생성을 시작하는 데 권장되는 방법입니다.

46.1.3. 사전 요구 사항

camel-archetype-api-component archetype을 실행하기 위한 유일한 전제 조건은 Apache Maven이 설치되고 Maven settings.xml 파일이 표준 Fuse 리포지토리를 사용하도록 구성되어 있다는 것입니다.

46.1.4. Maven archetype 호출

예제 URI 체계를 사용하는 예제 구성 요소를 생성하려면 다음과 같이 camel-archetype-api-component archetype을 호출하여 새 Maven 프로젝트를 생성합니다.

mvn archetype:generate \
-DarchetypeGroupId=org.apache.camel.archetypes \
-DarchetypeArtifactId=camel-archetype-api-component \
-DarchetypeVersion=2.23.2.fuse-790054-redhat-00001 \
-DgroupId=org.jboss.fuse.example \
-DartifactId=camel-api-example \
-Dname=Example \
-Dscheme=example \
-Dversion=1.0-SNAPSHOT \
-DinteractiveMode=false
참고

각 줄 끝에 있는 백슬래시 문자 \ 는 줄 연속을 나타내며 Linux 및 UNIX 플랫폼에서만 작동합니다. Windows 플랫폼에서 백슬래시를 제거하고 모든 인수를 한 줄에 배치합니다.

46.1.5. 옵션

옵션은 구문을 사용하여 archetype generation 명령에 제공됩니다. -DName=Value. 대부분의 옵션은 이전 mvn archetype:generate 명령에 표시된 대로 설정해야 하지만 생성된 프로젝트를 사용자 지정하도록 몇 가지 옵션을 수정할 수 있습니다. 다음 표에서는 생성된 API 구성 요소 프로젝트를 사용자 지정하는 데 사용할 수 있는 옵션을 보여줍니다.

이름설명

groupId

(일반 Maven 옵션) 생성된 Maven 프로젝트의 그룹 ID를 지정합니다. 기본적으로 이 값은 생성된 클래스의 Java 패키지 이름도 정의합니다. 따라서 원하는 Java 패키지 이름과 일치하도록 이 값을 선택하는 것이 좋습니다.

artifactId

(일반 Maven 옵션) 생성된 Maven 프로젝트의 아티팩트 ID를 지정합니다.

name

API 구성 요소의 이름입니다. 이 값은 생성된 코드에서 클래스 이름을 생성하는 데 사용됩니다(이름은 대문자로 시작하는 것이 좋습니다).

스키마

이 구성 요소의 URI에서 사용할 기본 스키마입니다. 이 스키마가 기존 Camel 구성 요소의 계획과 충돌하지 않도록 해야 합니다.

archetypeVersion

(일반 Maven 옵션) 구성 요소를 배포하려는 컨테이너에서 사용하는 Apache Camel 버전이어야 합니다. 그러나 필요한 경우 프로젝트를 생성한 Maven 종속 항목의 버전을 수정할 수도 있습니다.

46.1.6. 생성된 프로젝트의 구조

코드 생성 단계가 성공적으로 완료되면 새 Maven 프로젝트가 포함된 새 디렉터리 camel-api-example 이 표시되어야 합니다. camel-api-example 디렉터리 내부를 살펴보면 다음과 같은 일반적인 구조가 있음을 알 수 있습니다.

camel-api-example/
    pom.xml
    camel-api-example-api/
    camel-api-example-component/

프로젝트의 최상위 수준에서는 다음과 같이 두 개의 하위 프로젝트를 빌드하도록 구성된 집계 POM, pom.xml 입니다.

camel-api-example-api

API 하위 프로젝트( ArtifactId-api라고도 함)에는 구성 요소로 전환하려는 Java API가 있습니다. 직접 작성한 Java API에 API 구성 요소를 준비하는 경우 Java API 코드를 이 프로젝트에 직접 배치할 수 있습니다.

API 하위 프로젝트는 다음 목적 중 하나 이상에 사용할 수 있습니다.

  • Java API 코드를 패키징하려면(이미 Maven 패키지로 제공되지 않는 경우).
  • Java API에 대한 Javadoc을 생성하려면(API 구성 요소 프레임워크에 필요한 메타데이터 제공).
  • API 설명에서 Java API 코드를 생성하려면(예: REST API에 대한 WADL 설명에서).

그러나 경우에 따라 이러한 작업을 수행할 필요가 없을 수 있습니다. 예를 들어 API 구성 요소가 Maven 패키지에 Java API 및 Javadoc을 이미 제공하는 타사 API를 기반으로 하는 경우입니다. 이러한 경우 API 하위 프로젝트를 삭제할 수 있습니다.

camel-api-example-component
구성 요소 하위 프로젝트( ArtifactId-component라고도 함)에는 새 API 구성 요소의 구현이 포함됩니다. 여기에는 구성 요소 구현 클래스와 camel-api-component-maven 플러그인의 구성이 포함됩니다(Java API에서 API 매핑 클래스를 생성).

46.2. 생성된 API 하위 프로젝트

46.2.1. 개요

46.1절. “Maven Archetype을 사용하여 코드 생성” 에 설명된 대로 새 Maven 프로젝트를 생성했다고 가정하면 이제 camel-api-example/camel-api-example-api 프로젝트 디렉터리 아래에 Java API를 패키징하기 위한 Maven 하위 프로젝트를 찾을 수 있습니다. 이 섹션에서는 생성된 예제 코드를 자세히 살펴보고 작동 방식을 설명합니다.

46.2.2. Sample Java API

생성된 예제 코드에는 예제 API 구성 요소가 기반으로 하는 샘플 Java API가 포함되어 있습니다. 샘플 Java API는 두 개의 Hello World 클래스인 ExampleJavadocHelloExampleFileHello 로 구성된 비교적 간단합니다.

46.2.3. ExampleJavadocHello 클래스

예 46.1. “ExampleJavadocHello 클래스” 샘플 Java API의 ExampleJavadocHello 클래스를 보여줍니다. 클래스 이름에서 알 수 있듯이 이 특정 클래스는 Javadoc에서 매핑 메타데이터를 제공하는 방법을 보여주는 데 사용됩니다.

예 46.1. ExampleJavadocHello 클래스

// Java
package org.jboss.fuse.example.api;

/**
 * Sample API used by Example Component whose method signatures are read from Javadoc.
 */
public class ExampleJavadocHello {

    public String sayHi() {
        return "Hello!";
    }

    public String greetMe(String name) {
        return "Hello " + name;
    }

    public String greetUs(String name1, String name2) {
            return "Hello " + name1 + ", " + name2;
    }
}

46.2.4. ExampleFileHello 클래스

예 46.2. “ExampleFileHello 클래스” 샘플 Java API의 ExampleFileHello 클래스를 보여줍니다. 클래스 이름에서 알 수 있듯이 이 특정 클래스는 서명 파일에서 매핑 메타데이터를 제공하는 방법을 표시하는 데 사용됩니다.

예 46.2. ExampleFileHello 클래스

// Java
package org.jboss.fuse.example.api;

/**
 * Sample API used by Example Component whose method signatures are read from File.
 */
public class ExampleFileHello {

    public String sayHi() {
        return "Hello!";
    }

    public String greetMe(String name) {
        return "Hello " + name;
    }

    public String greetUs(String name1, String name2) {
            return "Hello " + name1 + ", " + name2;
    }
}

46.2.5. ExampleJavadocHello에 대한 Javadoc 메타데이터 생성

ExampleJavadocHello 의 메타데이터는 Javadoc로 제공되므로 샘플 Java API에 대한 Javadoc을 생성하고 camel-api-example-api Maven 아티팩트에 설치해야 합니다. API POM 파일 camel-api-example-api/pom.xml 에서는 Maven 빌드 중에 이 단계를 자동으로 수행하도록 maven-javadoc-plugin 을 구성합니다.

46.3. 생성된 구성 요소 하위 프로젝트

46.3.1. 개요

새 구성 요소를 구축하기 위한 Maven 하위 프로젝트는 camel-api-example/camel-api-example-component 프로젝트 디렉터리에 있습니다. 이 섹션에서는 생성된 예제 코드를 자세히 살펴보고 작동 방식을 설명합니다.

46.3.2. 구성 요소 POM에 Java API 제공

Java API는 구성 요소 POM에서 종속성으로 제공해야 합니다. 예를 들어 샘플 Java API는 다음과 같이 구성 요소 POM 파일에서 종속성으로 정의됩니다. camel-api-example-component/pom.xml.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

  ...
  <dependencies>
    ...
    <dependency>
      <groupId>org.jboss.fuse.example</groupId>
      <artifactId>camel-api-example-api</artifactId>
      <version>1.0-SNAPSHOT</version>
    </dependency>
    ...
  </dependencies>
  ...
</project>

46.3.3. 구성 요소 POM에 Javadoc 메타데이터 제공

Java API의 전체 또는 일부에 Javadoc 메타데이터를 사용하는 경우 Javadoc을 구성 요소 POM의 종속성으로 제공해야 합니다. 이 종속성에 대해 알아야 할 두 가지 사항이 있습니다.

  • Javadoc의 Maven 좌표는 다음과 같이 분류자 요소도 지정해야 한다는 점을 제외하고 Java API와 거의 동일합니다.

    <classifier>javadoc</classifier>
  • 다음과 같이 Javadoc이 제공된 범위를 갖도록 선언해야 합니다.

    <scope>provided</scope>

예를 들어 구성 요소 POM에서 Javadoc 종속성은 다음과 같이 정의됩니다.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

  ...
  <dependencies>
    ...
    <!-- Component API javadoc in provided scope to read API signatures -->
    <dependency>
      <groupId>org.jboss.fuse.example</groupId>
      <artifactId>camel-api-example-api</artifactId>
      <version>1.0-SNAPSHOT</version>
      <classifier>javadoc</classifier>
      <scope>provided</scope>
    </dependency>
    ...
  </dependencies>
  ...
</project>

46.3.4. 예제 파일 Hello의 파일 메타데이터 정의

ExampleFileHello 의 메타데이터는 서명 파일에 제공됩니다. 일반적으로 이 파일은 수동으로 생성해야 하지만 메서드 서명 목록으로 구성된 간단한 형식(각 줄에 하나씩)이 있습니다. 예제 코드는 다음 콘텐츠가 포함된 서명 파일 file-sig-api.txt 디렉터리에 camel-api-example-component/signatures 를 제공합니다.

public String sayHi();
public String greetMe(String name);
public String greetUs(String name1, String name2);

서명 파일 형식에 대한 자세한 내용은 “서명 파일 메타데이터” 을 참조하십시오.

46.3.5. API 매핑 구성

API 구성 요소 프레임워크의 주요 기능 중 하나는 API 매핑 을 수행하기 위해 자동으로 코드를 생성한다는 것입니다. 즉, 엔드포인트 URI를 Java API에서 메서드 호출에 매핑하는 스텁 코드를 생성합니다. API 매핑의 기본 입력은 Java API, Javadoc 메타데이터 및/또는 서명 파일 메타데이터입니다.

API 매핑을 수행하는 구성 요소는 POM 구성 요소에 구성된 camel-api-component-maven-plugin Maven 플러그인입니다. 구성 요소 POM에서 다음 추출은 camel-api-component-maven-plugin 플러그인이 구성된 방법을 보여줍니다.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

  ...
  <build>
    <defaultGoal>install</defaultGoal>

    <plugins>
      ...
      <!-- generate Component source and test source -->
      <plugin>
        <groupId>org.apache.camel</groupId>
        <artifactId>camel-api-component-maven-plugin</artifactId>
        <executions>
          <execution>
            <id>generate-test-component-classes</id>
            <goals>
              <goal>fromApis</goal>
            </goals>
            <configuration>
              <apis>
                <api>
                  <apiName>hello-file</apiName>
                  <proxyClass>org.jboss.fuse.example.api.ExampleFileHello</proxyClass>
                  <fromSignatureFile>signatures/file-sig-api.txt</fromSignatureFile>
                </api>
                <api>
                  <apiName>hello-javadoc</apiName>
                  <proxyClass>org.jboss.fuse.example.api.ExampleJavadocHello</proxyClass>
                  <fromJavadoc/>
                </api>
              </apis>
            </configuration>
          </execution>
        </executions>
      </plugin>
      ...
    </plugins>
    ...
  </build>
  ...
</project>

플러그인은 Java API의 클래스를 구성하는 단일 apis 하위 요소가 포함된 구성 요소로 구성됩니다. 각 API 클래스는 다음과 같이 api 요소에 의해 구성됩니다.

apiName

API 이름은 API 클래스의 짧은 이름이며 엔드포인트 URI의 엔드포인트-접 두사 부분으로 사용됩니다.

참고

API가 단일 Java 클래스로 구성된 경우 apiName 요소를 비워 두어 끝점 이 중복되게 하고 “단일 API 클래스의 URI 형식” 에 표시된 형식을 사용하여 끝점 URI를 지정할 수 있습니다.

proxyClass
proxy class 요소는 API 클래스의 정규화된 이름을 지정합니다.
fromJavadoc
API 클래스가 Javadoc 메타데이터와 함께 제공되는 경우 fromJavadoc 요소를 포함하여 이를 지정해야 하며 Javadoc 자체는 Maven 파일에 제공된 종속성으로 지정해야 합니다( “구성 요소 POM에 Javadoc 메타데이터 제공”참조).
fromSignatureFile

API 클래스가 서명 파일 메타데이터와 함께 이 클래스의 콘텐츠가 서명 파일의 위치를 지정하는 fromSignatureFile 요소를 포함하여 이를 표시해야 합니다.

참고

서명 파일은 런타임이 아닌 빌드 시에만 필요하므로 Maven에서 빌드한 최종 패키지에 포함되지 않습니다.

46.3.6. 생성된 구성 요소 구현

API 구성 요소는 camel-api-example-component/src/main/java 디렉터리에 있는 다음 코어 클래스(모든 Camel 구성 요소에 구현되어야 함)로 구성됩니다.

ExampleComponent
구성 요소 자체를 나타냅니다. 이 클래스는 끝점 인스턴스의 팩토리 역할을 합니다(예: ExampleEndpoint의 인스턴스).
ExampleEndpoint
엔드포인트 URI를 나타냅니다. 이 클래스는 소비자 끝점(예: ExampleConsumer)의 팩토리 역할을 하며 생산자 끝점(예: ExampleProducer)의 팩토리 역할을 합니다.
ExampleConsumer
엔드포인트 URI에 지정된 위치에서 메시지를 사용할 수 있는 소비자 끝점의 구체적인 인스턴스를 나타냅니다.
ExampleProducer
생산자 엔드포인트의 구체적인 인스턴스를 나타내며 엔드포인트 URI에 지정된 위치로 메시지를 전송할 수 있습니다.
예제Configuration

을 사용하여 엔드포인트 URI 옵션을 정의할 수 있습니다. 이 구성 클래스에서 정의한 URI 옵션은 특정 API 클래스에 연결되지 않습니다. 즉, 이러한 URI 옵션을 API 클래스 또는 메서드와 결합할 수 있습니다. 예를 들어 원격 서비스에 연결하기 위해 사용자 이름 및 암호 자격 증명을 선언해야 하는 경우 이 기능이 유용할 수 있습니다. ExampleConfiguration 클래스의 기본 목적은 API 클래스 또는 API 인터페이스를 구현하는 클래스를 인스턴스화하는 데 필요한 매개변수 값을 제공하는 것입니다. 예를 들어 생성자 매개 변수 또는 팩토리 메서드 또는 클래스의 매개 변수 값이 될 수 있습니다.For example, these could be constructor parameters, or parameter values for a factory method or class.

URI 옵션을 구현하려면 옵션 (옵션)을 구현하려면 접근자 메서드 쌍을 구현하고 옵션가져오기 및 옵션을 설정합니다. 구성 요소 프레임워크는 엔드포인트 URI를 자동으로 구문 분석하고 런타임에 옵션 값을 삽입합니다.

46.3.7. ExampleComponent 클래스

생성된 ExampleComponent 클래스는 다음과 같이 정의됩니다.

// Java
package org.jboss.fuse.example;

import org.apache.camel.CamelContext;
import org.apache.camel.Endpoint;
import org.apache.camel.spi.UriEndpoint;
import org.apache.camel.util.component.AbstractApiComponent;

import org.jboss.fuse.example.internal.ExampleApiCollection;
import org.jboss.fuse.example.internal.ExampleApiName;

/**
 * Represents the component that manages {@link ExampleEndpoint}.
 */
@UriEndpoint(scheme = "example", consumerClass = ExampleConsumer.class, consumerPrefix = "consumer")
public class ExampleComponent extends AbstractApiComponent<ExampleApiName, ExampleConfiguration, ExampleApiCollection> {

    public ExampleComponent() {
        super(ExampleEndpoint.class, ExampleApiName.class, ExampleApiCollection.getCollection());
    }

    public ExampleComponent(CamelContext context) {
        super(context, ExampleEndpoint.class, ExampleApiName.class, ExampleApiCollection.getCollection());
    }

    @Override
    protected ExampleApiName getApiName(String apiNameStr) throws IllegalArgumentException {
        return ExampleApiName.fromValue(apiNameStr);
    }

    @Override
    protected Endpoint createEndpoint(String uri, String methodName, ExampleApiName apiName,
                                      ExampleConfiguration endpointConfiguration) {
        return new ExampleEndpoint(uri, this, apiName, methodName, endpointConfiguration);
    }
}

이 클래스의 중요한 메서드는 새 엔드포인트 인스턴스를 생성하는 createEndpoint 입니다. 일반적으로 구성 요소 클래스의 기본 코드를 변경할 필요가 없습니다. 그러나 이 구성 요소와 동일한 라이프 사이클이 있는 다른 개체가 있는 경우 구성 요소 클래스에서 해당 개체를 사용할 수 있도록 할 수 있습니다(예: 해당 개체를 만드는 메서드를 추가하거나 해당 개체를 구성 요소에 삽입하여).

46.3.8. ExampleEndpoint 클래스

생성된 ExampleEndpoint 클래스는 다음과 같이 정의됩니다.

// Java
package org.jboss.fuse.example;

import java.util.Map;

import org.apache.camel.Consumer;
import org.apache.camel.Processor;
import org.apache.camel.Producer;
import org.apache.camel.spi.UriEndpoint;
import org.apache.camel.util.component.AbstractApiEndpoint;
import org.apache.camel.util.component.ApiMethod;
import org.apache.camel.util.component.ApiMethodPropertiesHelper;

import org.jboss.fuse.example.api.ExampleFileHello;
import org.jboss.fuse.example.api.ExampleJavadocHello;
import org.jboss.fuse.example.internal.ExampleApiCollection;
import org.jboss.fuse.example.internal.ExampleApiName;
import org.jboss.fuse.example.internal.ExampleConstants;
import org.jboss.fuse.example.internal.ExamplePropertiesHelper;

/**
 * Represents a Example endpoint.
 */
@UriEndpoint(scheme = "example", consumerClass = ExampleConsumer.class, consumerPrefix = "consumer")
public class ExampleEndpoint extends AbstractApiEndpoint<ExampleApiName, ExampleConfiguration> {

    // TODO create and manage API proxy
    private Object apiProxy;

    public ExampleEndpoint(String uri, ExampleComponent component,
                         ExampleApiName apiName, String methodName, ExampleConfiguration endpointConfiguration) {
        super(uri, component, apiName, methodName, ExampleApiCollection.getCollection().getHelper(apiName), endpointConfiguration);

    }

    public Producer createProducer() throws Exception {
        return new ExampleProducer(this);
    }

    public Consumer createConsumer(Processor processor) throws Exception {
        // make sure inBody is not set for consumers
        if (inBody != null) {
            throw new IllegalArgumentException("Option inBody is not supported for consumer endpoint");
        }
        final ExampleConsumer consumer = new ExampleConsumer(this, processor);
        // also set consumer.* properties
        configureConsumer(consumer);
        return consumer;
    }

    @Override
    protected ApiMethodPropertiesHelper<ExampleConfiguration> getPropertiesHelper() {
        return ExamplePropertiesHelper.getHelper();
    }

    protected String getThreadProfileName() {
        return ExampleConstants.THREAD_PROFILE_NAME;
    }

    @Override
    protected void afterConfigureProperties() {
        // TODO create API proxy, set connection properties, etc.
        switch (apiName) {
            case HELLO_FILE:
                apiProxy = new ExampleFileHello();
                break;
            case HELLO_JAVADOC:
                apiProxy = new ExampleJavadocHello();
                break;
            default:
                throw new IllegalArgumentException("Invalid API name " + apiName);
        }
    }

    @Override
    public Object getApiProxy(ApiMethod method, Map<String, Object> args) {
        return apiProxy;
    }
}

API 구성 요소 프레임워크의 컨텍스트에서 끝점 클래스에서 수행하는 주요 단계 중 하나는 API 프록시 를 생성하는 것입니다. API 프록시는 대상 Java API의 인스턴스이며 엔드포인트에서 메서드를 호출합니다. Java API는 일반적으로 많은 클래스로 구성되므로 URI에 나타나는 엔드포인트-접 두사에 따라 적절한 API 클래스를 선택해야 합니다(UU에 일반 형식인 scheme://endpoint-prefix/endpoint).

46.3.9. 예제Consumer 클래스

생성된 ExampleConsumer 클래스는 다음과 같이 정의됩니다.

// Java
package org.jboss.fuse.example;

import org.apache.camel.Processor;
import org.apache.camel.util.component.AbstractApiConsumer;

import org.jboss.fuse.example.internal.ExampleApiName;

/**
 * The Example consumer.
 */
public class ExampleConsumer extends AbstractApiConsumer<ExampleApiName, ExampleConfiguration> {

    public ExampleConsumer(ExampleEndpoint endpoint, Processor processor) {
        super(endpoint, processor);
    }

}

46.3.10. ExampleProducer 클래스

생성된 ExampleProducer 클래스는 다음과 같이 정의됩니다.

// Java
package org.jboss.fuse.example;

import org.apache.camel.util.component.AbstractApiProducer;

import org.jboss.fuse.example.internal.ExampleApiName;
import org.jboss.fuse.example.internal.ExamplePropertiesHelper;

/**
 * The Example producer.
 */
public class ExampleProducer extends AbstractApiProducer<ExampleApiName, ExampleConfiguration> {

    public ExampleProducer(ExampleEndpoint endpoint) {
        super(endpoint, ExamplePropertiesHelper.getHelper());
    }
}

46.3.11. 구성 클래스 예

생성된 ExampleConfiguration 클래스는 다음과 같이 정의됩니다.

// Java
package org.jboss.fuse.example;

import org.apache.camel.spi.UriParams;

/**
 * Component configuration for Example component.
 */
@UriParams
public class ExampleConfiguration {

    // TODO add component configuration properties
}

URI 옵션, 옵션 , 옵션을 이 클래스에 추가하고, 적절한 유형의 필드를 정의하고, 해당 접근자 메서드 쌍을 구현하려면 옵션을 가져오고 옵션을 설정합니다. 구성 요소 프레임워크는 엔드포인트 URI를 자동으로 구문 분석하고 런타임에 옵션 값을 삽입합니다.

참고

이 클래스는 모든 API 메서드와 결합할 수 있는 일반 URI 옵션을 정의하는 데 사용됩니다. 특정 API 메서드에 연결된 URI 옵션을 정의하려면 API 구성 요소 Maven 플러그인에서 추가 옵션을 구성합니다. 자세한 내용은 47.7절. “추가 옵션” 을 참조하십시오.

46.3.12. URI 형식

API 구성 요소 URI의 일반 형식을 상기합니다.

scheme://endpoint-prefix/endpoint?Option1=Value1&...&OptionN=ValueN

일반적으로 URI는 Java API에서 특정 메서드 호출에 매핑됩니다. 예를 들어 API 메서드 ExampleJavadocHello. CryostatMe("Jane Doe") 를 호출하려는 경우 다음과 같이 URI가 구성됩니다.

스키마
Maven archetype을 사용하여 코드를 생성할 때 지정된 API 구성 요소 체계입니다. 이 경우 스키마는 예제 입니다.
endpoint-prefix

camel-api-component-maven-plugin Maven 플러그인 구성으로 정의된 API 클래스에 매핑되는 API 이름입니다. ExampleJavadocHello 클래스의 경우 관련 구성은 다음과 같습니다.

<configuration>
  <apis>
    <api>
      <apiName>hello-javadoc</apiName>
      <proxyClass>org.jboss.fuse.example.api.ExampleJavadocHello</proxyClass>
      <fromJavadoc/>
    </api>
    ...
  </apis>
</configuration>

필수 endpoint-prefixhello-javadoc 임을 보여줍니다.

endpoint
엔드포인트 는 메서드 이름( Me )에 매핑됩니다.
Option1=Value1
URI 옵션은 메서드 매개변수를 지정합니다. Cryo statMe(String name) 메서드는 name =Jane%20Doe 로 지정할 수 있는 단일 매개변수인 name을 사용합니다. 옵션에 대한 기본값을 정의하려면 interceptProperties 메서드를 재정의하여 이 작업을 수행할 수 있습니다( 46.4절. “프로그래밍 모델”참조).

URI 조각을 통합하면 다음 URI를 사용하여 ExampleJavadocHello. CryostatMe("Jane Doe") 를 호출할 수 있습니다.

example://hello-javadoc/greetMe?name=Jane%20Doe

46.3.13. 기본 구성 요소 인스턴스

예제 URI 체계를 기본 구성 요소 인스턴스에 매핑하기 위해 Maven archetype은 camel-api-example-component 하위 프로젝트 아래에 다음 파일을 생성합니다.

src/main/resources/META-INF/services/org/apache/camel/component/example

이 리소스 파일은 Camel 코어에서 예제 URI 체계와 관련된 구성 요소를 식별할 수 있는 것입니다. 경로에서 example:// URI를 사용할 때마다 Camel은 classpath를 검색하여 해당 예제 리소스 파일을 찾습니다. 예제 파일에는 다음과 같은 내용이 있습니다.

class=org.jboss.fuse.example.ExampleComponent

이를 통해 Camel 코어는 ExampleComponent 구성 요소의 기본 인스턴스를 생성할 수 있습니다. 이 파일을 편집해야 하는 유일한 시간은 구성 요소 클래스의 이름을 리팩터링하는 것입니다.

46.4. 프로그래밍 모델

46.4.1. 개요

API 구성 요소 프레임워크의 컨텍스트에서 주요 구성 요소 구현 클래스는 org.apache.camel.util.component 패키지의 기본 클래스에서 파생됩니다. 이러한 기본 클래스는 구성 요소를 구현할 때 선택적으로 재정의할 수 있는 몇 가지 메서드를 정의합니다. 이 섹션에서는 해당 방법에 대한 간략한 설명과 자체 구성 요소 구현에서 사용하는 방법을 설명합니다.

46.4.2. 구현할 구성 요소 메서드

일반적으로 수정할 필요가 없는 생성된 메서드 구현 외에도 Component 클래스에서 다음 메서드 중 일부를 선택적으로 재정의할 수 있습니다.In addition to the generated method implementations (which you usually do not need to modify), you can optionally override some of the following methods in the Component class:

doStart()
(선택 사항) 콜드 시작 중에 구성 요소에 대한 리소스를 생성하는 콜백입니다. 다른 접근 방식은 지연 초기화 전략을 채택하는 것입니다(필요한 경우에만 리소스를 생성). 사실 지연 초기화는 종종 최상의 전략이므로 doStart 방법이 필요하지 않은 경우가 많습니다.
doStop()

(선택 사항) 구성 요소가 중지되는 동안 코드를 호출하는 콜백입니다. 구성 요소를 중지하면 모든 리소스가 종료되고 내부 상태가 삭제되고 캐시가 지워집니다.

참고

Camel은 해당 doStart 가 호출되지 않은 경우에도 현재 CamelContext 가 종료되면 항상 doStop 이 호출되도록 보장합니다.

doShutdown
(선택 사항) CamelContext 가 종료되는 동안 코드를 호출하는 콜백입니다. 중지된 구성 요소를 다시 시작할 수 있지만(일차 시작의 의미) 종료되는 구성 요소는 완전히 완료됩니다. 따라서 이 콜백은 구성 요소에 속하는 리소스를 확보할 수 있는 마지막 기회를 나타냅니다.

46.4.3. Component 클래스에서 구현해야 할 다른 것은 무엇입니까?

Component 클래스는 구성 요소 개체 자체와 동일한 (또는 유사한) 라이프 사이클이 있는 개체에 대한 참조를 보유하는 자연적인 위치입니다. 예를 들어 구성 요소가 OAuth 보안을 사용하는 경우 Component 클래스에 필요한 OAuth 개체에 대한 참조를 유지하고 OAuth 개체를 생성하기 위해 Component 클래스에 메서드를 정의하는 것이 자연스럽습니다.

46.4.4. 구현할 끝점 방법

다음과 같이 생성된 메서드 중 일부를 수정하고 필요한 경우 Endpoint 클래스에서 상속된 일부 메서드를 덮어쓸 수 있습니다.

afterConfigureProperties()

이 메서드에서 수행해야 하는 주요 작업은 API 이름과 일치하도록 적절한 유형의 프록시 클래스(API 클래스)를 생성하는 것입니다. API 이름( endpoint URI에서 이미 추출된)은 상속된 apiName 필드 또는 getApiName 접근자를 통해 사용할 수 있습니다. 일반적으로 apiName 필드에서 스위치를 수행하여 해당 프록시 클래스를 생성합니다. 예를 들면 다음과 같습니다.

// Java
private Object apiProxy;
...
@Override
protected void afterConfigureProperties() {
    // TODO create API proxy, set connection properties, etc.
    switch (apiName) {
        case HELLO_FILE:
            apiProxy = new ExampleFileHello();
            break;
        case HELLO_JAVADOC:
            apiProxy = new ExampleJavadocHello();
            break;
        default:
            throw new IllegalArgumentException("Invalid API name " + apiName);
    }
}
getApiProxy(ApiMethod 메서드, Map<String, Object> args)

ConfigureProperties 이후에 생성한 프록시 인스턴스를 반환하려면 이 메서드를 재정의합니다. 예를 들면 다음과 같습니다.

@Override
public Object getApiProxy(ApiMethod method, Map<String, Object> args) {
    return apiProxy;
}

특별한 경우에는 API 메서드 및 인수에 따라 프록시를 선택할 수 있습니다. getApiProxy 는 필요한 경우 이 접근 방식을 유연하게 수행할 수 있습니다.

doStart()
(선택 사항) 콜드 시작 중에 리소스를 생성하는 콜백입니다. Component.doStart() 와 동일한 의미 체계가 있습니다.
doStop()
(선택 사항) 구성 요소가 중지되는 동안 코드를 호출하는 콜백입니다. Component.doStop() 과 동일한 의미 체계가 있습니다.
doShutdown
(선택 사항) 구성 요소를 종료하는 동안 코드를 호출하는 콜백입니다. Component.doShutdown() 과 동일한 의미가 있습니다.
interceptPropertyNames(Set<String> propertyNames)

(선택 사항) API 구성 요소 프레임워크는 끝점 URI 및 제공된 옵션 값을 사용하여 호출할 메서드를 결정합니다(대신 및 별칭으로 인해 모호함). 그러나 구성 요소가 내부적으로 옵션 또는 메서드 매개 변수를 추가하는 경우 호출할 올바른 방법을 결정하기 위해 프레임워크가 도움이 필요할 수 있습니다. 이 경우 interceptPropertyNames 메서드를 재정의하고 propertyNames 세트에 추가(hidden 또는 implicit) 옵션을 추가해야 합니다. 메서드 매개 변수의 전체 목록이 propertyNames 세트에 제공되면 프레임 워크에서 호출할 올바른 메서드를 식별할 수 있습니다.

참고

Endpoint,Producer 또는 Consumer 클래스 수준에서 이 메서드를 재정의할 수 있습니다. 기본 규칙은 옵션이 생산자 엔드포인트와 소비자 엔드포인트 모두에 영향을 미치는 경우 Endpoint 클래스의 메서드를 재정의합니다.

interceptProperties(Map<String,Object> 속성)

(선택 사항) 이 메서드를 재정의하여 API 메서드를 호출하기 전에 옵션의 실제 값을 수정하거나 설정할 수 있습니다. 예를 들어 필요한 경우 이 방법을 사용하여 일부 옵션의 기본값을 설정할 수 있습니다. 실제로 interceptPropertyNames 메서드와 interceptProperty 메서드를 모두 재정의해야 하는 경우가 많습니다.

참고

Endpoint,Producer 또는 Consumer 클래스 수준에서 이 메서드를 재정의할 수 있습니다. 기본 규칙은 옵션이 생산자 엔드포인트와 소비자 엔드포인트 모두에 영향을 미치는 경우 Endpoint 클래스의 메서드를 재정의합니다.

46.4.5. 구현할 소비자 방법

다음과 같이 Consumer 클래스에서 상속된 일부 메서드를 선택적으로 재정의할 수 있습니다.

interceptPropertyNames(Set<String> propertyNames)
(선택 사항) 이 메서드의 의미 체계는 Endpoint.interceptPropertyNames와 유사합니다.
interceptProperties(Map<String,Object> 속성)
(선택 사항) 이 방법의 의미 체계는 Endpoint.interceptProperties와 유사합니다.
doInvokeMethod(Map<String, Object> args)

(선택 사항) 이 메서드를 재정의하면 Java API 메서드 호출을 가로챌 수 있습니다. 이 메서드를 재정의하는 가장 일반적인 이유는 메서드 호출에 대한 오류 처리를 사용자 지정하는 것입니다. 예를 들어 doInvokeMethod 를 재정의하는 일반적인 방법은 다음 코드 조각에 표시됩니다.

// Java
@Override
protected Object doInvokeMethod(Map<String, Object> args) {
    try {
        return super.doInvokeMethod(args);
    } catch (RuntimeCamelException e) {
        // TODO - Insert custom error handling here!
        ...
    }
}

Java API 메서드가 호출되도록 이 구현의 일정 시점에서 super-class에서 doInvokeMethod 를 호출해야 합니다.

interceptResult(Object methodResult, Exchange resultExchange)
(선택 사항) API 메서드 호출 결과에 대해 몇 가지 추가 처리를 수행합니다. 예를 들어 현재 Camel exchange 오브젝트인 resultExchange 에 사용자 지정 헤더를 추가할 수 있습니다.
오브젝트 splitResult(오브젝트 결과)

(선택 사항) 메서드 API 호출 결과가 java.util.Collection 개체 또는 Java 배열인 경우 API 구성 요소 프레임워크에서 결과를 여러 교환 개체로 분할합니다(단일 호출 결과가 여러 메시지로 변환됨).

기본 동작을 변경하려면 소비자 끝점에서 splitResult 메서드를 덮어쓸 수 있습니다. 결과 인수에는 API 메시지 호출 결과가 포함됩니다. 결과를 분할하려면 배열 유형을 반환해야 합니다.

참고

끝점 URI에서 consumer.splitResult=false 를 설정하여 기본 분할 동작을 전환할 수도 있습니다.

46.4.6. 구현할 생산자 메서드

다음과 같이 Producer 클래스에서 상속된 일부 메서드를 선택적으로 재정의할 수 있습니다.

interceptPropertyNames(Set<String> propertyNames)
(선택 사항) 이 메서드의 의미 체계는 Endpoint.interceptPropertyNames와 유사합니다.
interceptProperties(Map<String,Object> 속성)
(선택 사항) 이 방법의 의미 체계는 Endpoint.interceptProperties와 유사합니다.
doInvokeMethod(Map<String, Object> args)
(선택 사항) 이 방법의 의미 체계는 Consumer.doInvokeMethod 와 유사합니다.
interceptResult(Object methodResult, Exchange resultExchange)
(선택 사항) 이 방법의 의미 체계는 Consumer.interceptResult 와 유사합니다.
참고

Producer.splitResult() 메서드는 호출되지 않으므로 API 메서드를 분할하면 소비자 끝점에 사용할 수 있는 것과 동일한 방식으로 생성할 수 없습니다. 생산자 엔드포인트에 유사한 효과를 얻으려면 Camel의 split() DSL 명령(표준 엔터프라이즈 통합 패턴 중 하나)을 사용하여 컬렉션 또는 배열 결과를 분할할 수 있습니다.

46.4.7. 소비자 폴링 및 스레딩 모델

API 구성 요소 프레임워크에서 소비자 끝점의 기본 스레딩 모델은 폴링 소비자로 예약됩니다. 이는 소비자 끝점의 API 메서드가 정규 스케줄링된 시간 간격에 호출됨을 의미합니다. 자세한 내용은 “예약된 폴링 소비자 구현” 에서 참조하십시오.

46.5. 샘플 구성 요소 구현

46.5.1. 개요

Apache Camel과 함께 배포된 여러 구성 요소는 API 구성 요소 프레임워크를 통해 구현되었습니다. 프레임워크를 사용하여 Camel 구성 요소를 구현하는 기술에 대해 자세히 알아보려면 이러한 구성 요소 구현의 소스 코드를 연구하는 것이 좋습니다.

46.5.2. Box.com

Camel Box 구성 요소는 API 구성 요소 프레임워크를 사용하여 타사 Box.com Java SDK를 모델링하고 호출하는 방법을 보여줍니다. 또한 Box.com의 긴 폴링 API를 지원하기 위해 프레임워크를 조정하여 소비자 폴링을 사용자 지정하는 방법을 보여줍니다.

46.5.3. GoogleDrive

Camel Google Cryostat 구성 요소는 API 구성 요소 프레임워크에서 Method Object 스타일 Google API도 처리하는 방법을 보여줍니다. 이 경우 URI 옵션은 메서드 오브젝트에 매핑되며 소비자 및 생산자에서 doInvoke 메서드를 재정의하여 호출됩니다.

46.5.4. Olingo2

Camel Olingo2 구성 요소는 API 구성 요소 프레임워크를 사용하여 콜백 기반 비동기 API를 래핑하는 방법을 보여줍니다. 이 예에서는 HTTP NIO 연결과 같은 기본 리소스로 비동기 처리를 푸시하여 Camel 끝점을 더 효율적으로 만드는 방법을 보여줍니다.

47장. API 구성 요소 Maven 플러그인 구성

초록

이 장에서는 API 구성 요소 Maven 플러그인에서 사용할 수 있는 모든 구성 옵션에 대한 참조를 제공합니다.

47.1. 플러그인 구성 개요

47.1.1. 개요

API 구성 요소 Maven 플러그인의 주요 용도인 camel-api-component-maven-plugin 은 엔드포인트 URI와 API 메서드 호출 간의 매핑을 구현하는 API 매핑 클래스를 생성하는 것입니다. API 구성 요소 Maven 플러그인의 구성을 편집하여 API 매핑의 다양한 측면을 사용자 지정할 수 있습니다.

47.1.2. 생성된 코드의 위치

API 구성 요소 Maven 플러그인에서 생성한 API 매핑 클래스는 기본적으로 다음 위치에 배치됩니다.

ProjectName-component/target/generated-sources/camel-component

47.1.3. 사전 요구 사항

API 구성 요소 Maven 플러그인에 대한 주요 입력은 Java API 클래스 및 Javadoc 메타데이터입니다. 이는 플러그인에서 일반 Maven 종속 항목으로 선언하여 사용할 수 있습니다(Javadoc Maven 종속 항목은 제공된 범위로 선언해야 함).

47.1.4. 플러그인 설정

API 구성 요소 Maven 플러그인을 설정하는 권장 방법은 API 구성 요소 archetype을 사용하여 시작점 코드를 생성하는 것입니다. 이렇게 하면 프로젝트에 맞게 사용자 지정할 수 있는 ProjectName-component/pom.xml 파일에 기본 플러그인 구성이 생성됩니다. 플러그인 설정의 주요 측면은 다음과 같습니다.

  1. 필수 Java API 및 Javadoc 메타데이터에 대해 Maven 종속성을 선언해야 합니다.
  2. 플러그인의 기본 구성은 pluginManagement 범위(사용할 플러그인의 버전도 정의)에 선언됩니다.
  3. 플러그인 인스턴스 자체는 선언 및 구성됩니다.
  4. build-helper-maven 플러그인은 target/generated-sources/camel-component 디렉터리에서 생성된 소스를 가져와 Maven 빌드에 포함하도록 구성됩니다.

47.1.5. 기본 구성 예

다음 POM 파일 추출은 API 구성 요소 archetype을 사용하여 코드가 생성될 때 Maven 플러그인에 정의된 API 구성 요소 Maven 플러그인의 기본 구성을 보여줍니다.

<?xml version="1.0" encoding="UTF-8"?>
<project ...>
  ...
  <build>
    ...
    <pluginManagement>
      <plugins>
        <plugin>
          <groupId>org.apache.camel</groupId>
          <artifactId>camel-api-component-maven-plugin</artifactId>
          <version>2.23.2.fuse-790054-redhat-00001</version>
          <configuration>
            <scheme>${schemeName}</scheme>
            <componentName>${componentName}</componentName>
            <componentPackage>${componentPackage}</componentPackage>
            <outPackage>${outPackage}</outPackage>
          </configuration>
        </plugin>
      </plugins>
    </pluginManagement>
    ...
  </build>
  ...
</project

pluginManagement 범위에 지정된 구성은 플러그인에 대한 기본 설정을 제공합니다. 실제로 플러그인 인스턴스를 생성하지 않지만 모든 API 구성 요소 플러그인 인스턴스에서 기본 설정을 사용합니다.

47.1.6. 기본 구성

플러그인 버전( 버전 요소)을 지정하는 것 외에도 이전 기본 구성은 다음과 같은 구성 속성을 지정합니다.

스키마
이 API 구성 요소의 URI 스키마입니다.
componentName
이 API 구성 요소의 이름입니다(생성된 클래스 이름에 접두사로 사용됨).
componentPackage
API 구성 요소 Maven archetype에서 생성한 클래스를 포함하는 Java 패키지를 지정합니다. 이 패키지는 기본 maven-bundle-plugin 구성에서도 내보냅니다. 따라서 클래스를 공개적으로 표시하려면 이 Java 패키지에 배치해야 합니다.
outPackage
생성된 API 매핑 클래스가 배치되는 Java 패키지를 지정합니다(API 구성 요소 Maven 플러그인에 의해 생성될 때). 기본적으로 이 값은 componentName 속성 값이고 .internal 접미사가 추가됩니다. 이 패키지는 기본 maven-bundle-plugin 구성에 의해 비공개로 선언됩니다. 따라서 클래스를 개인용으로 사용하려면 이 Java 패키지에 배치해야 합니다.

47.1.7. 인스턴스 구성 예

다음 POM 파일 추출은 Maven 빌드 중에 API 매핑을 생성하도록 구성된 API 구성 요소 Maven 플러그인의 샘플 인스턴스를 보여줍니다.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

  ...
  <build>
    <defaultGoal>install</defaultGoal>

    <plugins>
      ...
      <!-- generate Component source and test source -->
      <plugin>
        <groupId>org.apache.camel</groupId>
        <artifactId>camel-api-component-maven-plugin</artifactId>
        <executions>
          <execution>
            <id>generate-test-component-classes</id>
            <goals>
              <goal>fromApis</goal>
            </goals>
            <configuration>
              <apis>
                <api>
                  <apiName>hello-file</apiName>
                  <proxyClass>org.jboss.fuse.example.api.ExampleFileHello</proxyClass>
                  <fromSignatureFile>signatures/file-sig-api.txt</fromSignatureFile>
                </api>
                <api>
                  <apiName>hello-javadoc</apiName>
                  <proxyClass>org.jboss.fuse.example.api.ExampleJavadocHello</proxyClass>
                  <fromJavadoc/>
                </api>
              </apis>
            </configuration>
          </execution>
        </executions>
      </plugin>
      ...
    </plugins>
    ...
  </build>
  ...
</project>

47.1.8. 기본 매핑 구성

플러그인은 Java API의 클래스를 구성하는 단일 apis 하위 요소가 포함된 구성 요소로 구성됩니다. 각 API 클래스는 다음과 같이 api 요소에 의해 구성됩니다.

apiName

API 이름은 API 클래스의 짧은 이름이며 엔드포인트 URI의 엔드포인트-접 두사 부분으로 사용됩니다.

참고

API가 단일 Java 클래스로 구성된 경우 apiName 요소를 비워 두어 끝점 이 중복되게 하고 “단일 API 클래스의 URI 형식” 에 표시된 형식을 사용하여 끝점 URI를 지정할 수 있습니다.

proxyClass
이 요소는 API 클래스의 정규화된 이름을 지정합니다.
fromJavadoc
API 클래스가 Javadoc 메타데이터와 함께 제공되는 종속성으로 fromJavadoc 요소와 Javadoc 자체도 지정해야 합니다.
fromSignatureFile

API 클래스가 서명 파일 메타데이터와 함께 이 클래스의 콘텐츠가 서명 파일의 위치를 지정하는 fromSignatureFile 요소를 포함하여 이를 표시해야 합니다.

참고

서명 파일은 런타임이 아닌 빌드 시에만 필요하므로 Maven에서 빌드한 최종 패키지에 포함되지 않습니다.

47.1.9. API 매핑 사용자 정의

API 매핑의 다음 측면은 플러그인을 구성하여 사용자 지정할 수 있습니다.

  • 메서드 별칭 Cryostat-에서 별칭 구성 요소를 사용하여 API 메서드에 대한 추가 이름( aliases )을 정의할 수 있습니다. 자세한 내용은 47.3절. “메서드 별칭”의 내용을 참조하십시오.
  • Cryostat 옵션 Cryostat- Cryostat Options 구성 요소를 사용하여 기본값이 null 인 메서드 인수를 선언할 수 있습니다. 자세한 내용은 47.4절. “Cryostat 옵션”의 내용을 참조하십시오.
  • API 매핑이 구현되는 방식으로 인해 인수 이름 대체 Cryostat-에서 특정 API 클래스의 모든 메서드의 인수가 동일한 네임스페이스에 속합니다. 동일한 이름의 두 인수가 다른 유형으로 선언되면 충돌이 발생합니다. 이러한 이름 충돌을 방지하려면 대체 구성 요소를 사용하여 메서드 인수의 이름을 변경할 수 있습니다( URI에 표시됨). 자세한 내용은 47.5절. “인수 이름 하위”의 내용을 참조하십시오.
  • 인수를 제외하면 Java 인수를 URI 옵션에 매핑할 때 매핑에서 특정 인수를 제외해야 하는 경우가 있습니다. excludeConfigNames 요소 또는 excludeConfigTypes 요소를 지정하여 원하지 않는 인수를 필터링할 수 있습니다. 자세한 내용은 47.6절. “제외된 인수”의 내용을 참조하십시오.
  • 추가 옵션 즉, Java API의 일부가 아닌 추가 옵션을 정의할 수 있습니다. extraOptions 구성 요소를 사용하여 이 작업을 수행할 수 있습니다.

47.1.10. Javadoc 메타데이터 구성

특정 콘텐츠를 무시하거나 명시적으로 포함하도록 Javadoc 메타데이터를 필터링할 수 있습니다. 이 작업을 수행하는 방법에 대한 자세한 내용은 47.2절. “Javadoc 옵션” 을 참조하십시오.

47.1.11. 서명 파일 메타데이터 구성

Javadoc을 사용할 수 없는 경우 파일에 서명하여 필요한 매핑 메타데이터를 제공할 수 있습니다. fromSignatureFile 은 해당 서명 파일의 위치를 지정하는 데 사용됩니다. 특별한 옵션은 없습니다.

47.2. Javadoc 옵션

47.2.1. 개요

Java API의 메타데이터가 Javadoc에서 제공하는 경우 일반적으로 옵션 없이 fromJavadoc 요소를 지정하는 것으로 충분합니다. 그러나 API 매핑에 전체 Java API를 포함하지 않으려는 경우 Javadoc 메타데이터를 필터링하여 콘텐츠를 사용자 지정할 수 있습니다. 즉, API 구성 요소 Maven 플러그인은 Javadoc 메타데이터를 통해 API 매핑을 생성하므로 Javadoc 메타데이터의 원하지 않는 부분을 필터링하여 생성된 API 매핑의 범위를 사용자 지정할 수 있습니다.

47.2.2. 구문

fromJavadoc 요소는 다음과 같이 선택적 하위 요소로 구성할 수 있습니다.

<fromJavadoc>
  <excludePackages>PackageNamePattern</excludePackages>
  <excludeClasses>ClassNamePattern</excludeClasses>
  <excludeMethods>MethodNamePattern</excludeMethods>
  <includeMethods>MethodNamePattern</includeMethods>
  <includeStaticMethods>[true|false]<includeStaticMethods>
</fromJavadoc>

47.2.3. 범위

다음 추출에 표시된 대로 fromJavadoc 요소는 선택적으로 apis 요소의 자식으로 및/또는 api 요소의 자식으로 표시될 수 있습니다.

<configuration>
  <apis>
    <api>
      <apiName>...</apiName>
      ...
      <fromJavadoc>...</fromJavadoc>
    </api>
    <fromJavadoc>...</fromJavadoc>
    ...
  </apis>
</configuration>

다음 범위에서 fromJavadoc 요소를 정의할 수 있습니다.

  • api 요소의 자식으로 kafka- Cryostatthe fromJavadoc 옵션은 api 요소에서 지정한 API 클래스에만 적용됩니다.
  • apis 요소의 자식으로 Cryostat-floatingthe fromJavadoc 옵션은 기본적으로 모든 API 클래스에 적용되지만 api 수준에서 재정의할 수 있습니다.

47.2.4. 옵션

다음 옵션은 fromJavadoc 의 하위 요소로 정의할 수 있습니다.

excludePackages
API 매핑 모델에서 Java 패키지를 제외하기 위한 정규식(java.util.regex 구문)을 지정합니다. 정규식과 일치하는 모든 패키지 이름도 제외되며 제외된 클래스에서 파생된 모든 클래스도 무시됩니다. 기본값은 javax?\.lang.\* 입니다.
excludeClasses
API 매핑에서 API 기본 클래스를 제외하기 위한 정규식(java.util.regex 구문)을 지정합니다. 정규식과 일치하는 모든 클래스 이름은 제외되며 제외된 클래스에서 파생된 모든 클래스도 무시됩니다.
excludeMethods
API 매핑 모델에서 메서드를 제외하기 위한 정규식(java.util.regex 구문)을 지정합니다.
includeMethods
API 매핑 모델의 메서드를 포함하는 정규식(java.util.regex 구문)을 지정합니다.
includeStaticMethods
true 인 경우 정적 메서드도 API 매핑 모델에 포함됩니다. 기본값은 false 입니다.

47.3. 메서드 별칭

47.3.1. 개요

종종 Java API에 표시되는 표준 메서드 이름 외에 지정된 메서드에 대한 추가 이름(별칭)을 정의하는 것이 유용할 수 있습니다. 특히 일반적인 경우는 속성 이름(예: 위젯)을 접근자 메서드(예: getWidget 또는 setWidget)의 별칭으로 사용할 수 있도록 허용하는 위치입니다.

47.3.2. 구문

aliases 요소는 다음과 같이 하나 이상의 alias 하위 요소로 정의할 수 있습니다.

<aliases>
  <alias>
    <methodPattern>MethodPattern</methodPattern>
    <methodAlias>Alias</methodAlias>
  </alias>
  ...
</aliases>

여기서 MethodPattern 은 Java API에서 메서드 이름과 일치하는 정규식(java.util.regex 구문)이며 일반적으로 패턴에는 캡처 그룹을 포함합니다. 별칭 은 이전 캡처 그룹의 텍스트를 사용할 수 있는 대체 표현식입니다(예: 첫 번째, 두 번째 또는 세 번째 캡처 그룹의 텍스트에 대해 $ 1,2 로 지정 또는 $3 ).

47.3.3. 범위

다음 추출에 표시된 것처럼 aliases 요소는 선택적으로 apis 요소의 자식으로 및/또는 api 요소의 자식으로 표시될 수 있습니다.

<configuration>
  <apis>
    <api>
      <apiName>...</apiName>
      ...
      <aliases>...</aliases>
    </api>
    <aliases>...</aliases>
    ...
  </apis>
</configuration>

다음 범위에서 aliases 요소를 정의할 수 있습니다.

  • api 요소의 자식으로 Cryostat- Cryostat 별칭 매핑은 api 요소에서 지정한 API 클래스에만 적용됩니다.
  • apis 요소의 자식으로 Cryostat-property- aliases 매핑은 기본적으로 모든 API 클래스에 적용되지만 api 수준에서 재정의할 수 있습니다.

47.3.4. 예제

다음 예제에서는 공통 get/set useful 메서드 패턴에 대한 별칭을 생성하는 방법을 보여줍니다.

<aliases>
  <alias>
    <methodPattern>[gs]et(.+)</methodPattern>
    <methodAlias>$1</methodAlias>
  </alias>
</aliases>

이전 별칭 정의를 사용하면 getWidget 또는 setWidget 중 하나의 별칭으로 위젯 을 사용할 수 있습니다. 캡처 그룹 (.+) 을 사용하여 메서드 이름의 후자 부분(예: )을 캡처합니다.

47.4. Cryostat 옵션

47.4.1. 개요

경우에 따라 메서드 인수가 null 로 기본값으로 설정되도록 하는 것이 적합할 수 있습니다. 그러나 이는 기본적으로 허용되지 않습니다. Java API의 메서드 인수 중 일부가 null 값을 사용하도록 허용하려면 Cryostat Options 요소를 사용하여 명시적으로 선언해야 합니다.

47.4.2. 구문

Cryo statOptions 요소는 다음과 같이 하나 이상의 Cryostat Option 하위 요소로 정의할 수 있습니다.

<nullableOptions>
  <nullableOption>ArgumentName</nullableOption>
  ...
</nullableOptions>

여기서 ArgumentName 은 Java API의 메서드 인수의 이름입니다.

47.4.3. 범위

다음 추출에 표시된 것처럼, Cryostat Options 요소는 선택적으로 apis 요소의 자식으로 및/또는 api 요소의 자식으로 표시될 수 있습니다.

<configuration>
  <apis>
    <api>
      <apiName>...</apiName>
      ...
      <nullableOptions>...</nullableOptions>
    </api>
    ...
    <nullableOptions>...</nullableOptions>
  </apis>
</configuration>

다음 범위에서 Cryo statOptions 요소를 정의할 수 있습니다.

  • api 요소의 자식으로 Cryostat- Cryo statOptions 매핑은 api 요소에서 지정한 API 클래스에만 적용됩니다.
  • apis 요소의 자식으로 Cryostat- Cryostat Options 매핑은 기본적으로 모든 API 클래스에 적용되지만 api 수준에서 재정의할 수 있습니다.

47.5. 인수 이름 하위

47.5.1. 개요

API 구성 요소 프레임워크를 사용하려면 각 프록시 클래스(Java API 클래스) 내에서 URI 옵션 이름이 고유 해야 합니다. 그러나 메서드 인수 이름에 항상 해당하는 것은 아닙니다. 예를 들어 API 클래스에서 다음 Java 메서드를 고려하십시오.

public void doSomething(int id, String name);
public void doSomethingElse(int id, String name);

Maven 프로젝트를 빌드할 때 camel-api-component-maven-pluginProxyClass 클래스의 모든 인수에 대한 getter 및 setter 메서드를 포함하는 구성 클래스인 ProxyClass EndpointConfiguration 을 생성합니다. 예를 들어 이전 메서드에서 플러그인에서 구성 클래스에서 다음 getter 및 setter 메서드를 생성합니다.

public int  getId();
public void setId(int id);
public String getName();
public void   setName(String name);

그러나 다음 예와 같이 id 인수가 다른 유형으로 여러 번 표시되는 경우 발생하는 작업은 다음과 같습니다.

public void doSomething(int id, String name);
public void doSomethingElse(int id, String name);
public String lookupByID(String id);

이 경우 int 를 반환하는 getId 메서드와 동일한 범위에서 문자열 을 반환하는 getId 메서드를 정의할 수 없기 때문에 코드 생성이 실패합니다. 이 문제에 대한 해결 방법은 인수 이름 대체를 사용하여 인수 이름 매핑을 URI 옵션 이름에 사용자 지정하는 것입니다.

47.5.2. 구문

substitutions 요소는 다음과 같이 하나 이상의 대체 하위 요소로 정의할 수 있습니다.

<substitutions>
  <substitution>
    <method>MethodPattern</method>
    <argName>ArgumentNamePattern</argName>
    <argType>TypeNamePattern</argType>
    <replacement>SubstituteArgName</replacement>
    <replaceWithType>[true|false]</replaceWithType>
  </substitution>
  ...
</substitutions>

여기서 argType 요소와 replaceWithType 요소는 선택 사항이며 생략할 수 있습니다.

47.5.3. 범위

다음 추출에 표시된 것처럼 대체 요소는 선택적으로 apis 요소의 자식으로 및/또는 api 요소의 자식으로 표시될 수 있습니다.

<configuration>
  <apis>
    <api>
      <apiName>...</apiName>
      ...
      <substitutions>...</substitutions>
    </api>
    <substitutions>...</substitutions>
    ...
  </apis>
</configuration>

다음 범위에서 substitutions 요소를 정의할 수 있습니다.

  • api 요소의 자식으로, 대체api 요소에서 지정한 API 클래스에만 적용됩니다.
  • apis 요소의 자식으로, 대체 는 기본적으로 모든 API 클래스에 적용되지만 api 수준에서 재정의할 수 있습니다.

47.5.4. 하위 요소

대체 요소는 다음 하위 요소로 정의할 수 있습니다.

method
Java API의 메서드 이름과 일치하도록 정규식(java.util.regex 구문)을 지정합니다.
argName
일치된 메서드의 인수 이름과 일치하도록 정규식(java.util.regex 구문)을 지정합니다. 여기서 패턴은 일반적으로 캡처 그룹을 포함합니다.
argType
(선택 사항) 인수 유형과 일치하도록 정규식(java.util.regex 구문)을 지정합니다. replaceWithType 옵션을 true 로 설정하면 일반적으로 이 정규식에서 캡처 그룹을 사용합니다.
교체
메서드 패턴의 특정 일치 항목인 argName 패턴 및 (선택 옵션으로) argType 패턴의 경우 replacement 요소는 대체 인수 이름(URI에서 사용)을 정의합니다. 대체 텍스트는 argName 정규식 패턴에서 캡처된 문자열을 사용하여 (구문, $ 1,2 달러,$3 구문을 사용하여 각각 첫 번째, 두 번째 또는 세 번째 캡처 그룹을 삽입함)을 사용하여 구성할 수 있습니다. 또는 replaceWithType 옵션을 true 로 설정하면 argType 정규식 패턴에서 캡처된 문자열을 사용하여 대체 텍스트를 구성할 수 있습니다.
replaceWithType
true 에서는 argType 정규식에서 캡처된 문자열을 사용하여 대체 텍스트가 구성되도록 지정합니다. 기본값은 false입니다.

47.5.5. 예제

다음 대체 예제에서는 접미사 Param 을 인수 이름에 추가하여 java.lang.String 유형의 모든 인수를 수정합니다.

<substitutions>
  <substitution>
    <method>^.+$</method>
    <argName>^.+$</argName>
    <argType>java.lang.String</argType>
    <replacement>$1Param</replacement>
    <replaceWithType>false</replaceWithType>
  </substitution>
</substitutions>

예를 들어 다음 메서드 시그니처가 제공됩니다.

public String greetUs(String name1, String name2);

이 메서드의 인수는 엔드포인트 URI에 있는 options, name1Paramname2Param 을 통해 지정됩니다.

47.6. 제외된 인수

47.6.1. 개요

Java 인수를 URI 옵션에 매핑할 때 특정 인수를 제외해야 하는 경우가 있습니다. camel-api-component-maven-plugin 플러그인 구성에서 excludeConfigNames 요소 또는 excludeConfigTypes 요소를 지정하여 원하지 않는 인수를 필터링할 수 있습니다.

47.6.2. 구문

excludeConfigNames 요소 및 excludeConfigTypes 요소는 다음과 같이 지정됩니다.

<excludeConfigNames>ArgumentNamePattern</excludeConfigNames>
<excludeConfigTypes>TypeNamePattern</excludeConfigTypes>

여기서 ArgumentNamePatternTypeNamePattern 은 각각 인수 이름과 인수 유형과 일치하는 정규식입니다.

47.6.3. 범위

다음 추출에 표시된 것처럼 excludeConfigNames 요소 및 excludeConfigTypes 요소는 선택적으로 apis 요소의 하위 요소 및/또는 api 요소의 하위 항목으로 표시될 수 있습니다.

<configuration>
  <apis>
    <api>
      <apiName>...</apiName>
      ...
      <excludeConfigNames>...</excludeConfigNames>
      <excludeConfigTypes>...</excludeConfigTypes>
    </api>
    <excludeConfigNames>...</excludeConfigNames>
    <excludeConfigTypes>...</excludeConfigTypes>
    ...
  </apis>
</configuration>

다음 범위에서 excludeConfigNames 요소와 excludeConfigTypes 요소를 정의할 수 있습니다.

  • api 요소의 자식으로서의 경우, 예외는 api 요소에서 지정한 API 클래스에만 적용됩니다.
  • apis 요소의 자식으로 Cryostat-floatingthe exclusions는 기본적으로 모든 API 클래스에 적용되지만 api 수준에서 재정의할 수 있습니다.

47.6.4. 요소

다음 요소를 사용하여 API 매핑에서 인수를 제외할 수 있습니다( URI 옵션으로 사용할 수 없음).

excludeConfigNames
인수 이름과 일치하는 인수를 제외하고 정규식(java.util.regex 구문)을 지정합니다.
excludeConfigTypes
인수 유형 일치에 따라 인수를 제외하는 정규식(java.util.regex 구문)을 지정합니다.

47.7. 추가 옵션

47.7.1. 개요

extraOptions 옵션은 일반적으로 더 간단한 옵션을 제공하여 복잡한 API 매개변수를 계산하거나 숨기는 데 사용됩니다. 예를 들어 API 메서드에는 URI에서 Cryostat의 일부로 더 쉽게 제공할 수 있는 Cryostat 옵션을 사용할 수 있습니다. 구성 요소는 부분을 추가 옵션으로 추가하고 내부적으로 Cryostat 매개 변수를 생성하여 이 작업을 수행할 수 있습니다. 이러한 추가 옵션의 구현을 완료하려면 EndpointConsumer 및/또는 EndpointProducer 클래스에서 interceptProperties 메서드를 재정의해야 합니다( 46.4절. “프로그래밍 모델”참조).

47.7.2. 구문

extraOptions 요소는 다음과 같이 하나 이상의 extraOption 하위 요소로 정의할 수 있습니다.

<extraOptions>
  <extraOption>
    <type>TypeName</type>
    <name>OptionName</name>
  </extraOption>
</extraOptions>

여기서 TypeName 은 추가 옵션의 정규화된 형식 이름이며 OptionName 은 추가 URI 옵션의 이름입니다.

47.7.3. 범위

다음 추출에 표시된 대로 extraOptions 요소는 선택적으로 apis 요소의 자식으로 및/또는 api 요소의 자식으로 표시될 수 있습니다.

<configuration>
  <apis>
    <api>
      <apiName>...</apiName>
      ...
      <extraOptions>...</extraOptions>
    </api>
    <extraOptions>...</extraOptions>
    ...
  </apis>
</configuration>

다음 범위에서 extraOptions 요소를 정의할 수 있습니다.

  • api 요소의 자식으로 추가Optionsapi 요소에서 지정한 API 클래스에만 적용됩니다.
  • apis 요소의 자식으로 추가Options 는 기본적으로 모든 API 클래스에 적용되지만 api 수준에서 재정의할 수 있습니다.

47.7.4. 하위 요소

extraOptions 요소는 다음 하위 요소로 정의할 수 있습니다.

type
추가 옵션의 정규화된 형식 이름을 지정합니다.
name
엔드포인트 URI에 표시되는 옵션 이름을 지정합니다.

47.7.5. 예제

다음 예제에서는 java.util.list<String> 유형의 추가 URI 옵션 customOption 을 정의합니다.

<extraOptions>
  <extraOption>
    <type>java.util.List<String></type>
    <name>customOption</name>
  </extraOption>
</extraOptions>

인덱스

Symbols

@Converter, 주석이 달린 컨버터 클래스 구현
간단한 프로세서
구현, 프로세서 인터페이스 구현
검색 파일, TypeConverter 파일 만들기
교환, 교환, 교환 인터페이스
copy(), 교환 방법
getExchangeId(), 교환 방법
getIn(), 메시지 헤더에 액세스, 교환 방법
getOut(), 교환 방법
getPattern(), 교환 방법
getProperties(), 교환 방법
getProperty(), 교환 방법
getUnitOfWork(), 교환 방법
removeProperty(), 교환 방법
setExchangeId(), 교환 방법
setIn(), 교환 방법
setOut(), 교환 방법
setProperty(), 교환 방법
setUnitOfWork(), 교환 방법
구성, 구성 요소 설치 및 구성, 자동 검색 구성
구성 요소
createEndpoint(), URI 구문 분석
방법, 구성 요소 메서드
정의, 구성 요소 인터페이스
구성 요소 접두사, 구성 요소
구현, 프로세서 인터페이스 구현, 동기 생산자를 구현하는 방법, 비동기 생산자 구현 방법
구현 단계, 형식 변환기를 구현하는 방법, 구현 단계
구현 주석 처리, 주석이 달린 컨버터 클래스 구현
구현할 인터페이스, 어떤 인터페이스를 구현해야 합니까?
기능 가능, 교환 패턴 테스트
끝점, endpoint
동기, 동기 생산자
동기 생산자
구현, 동기 생산자를 구현하는 방법
런타임 프로세스, 유형 변환 프로세스
매개변수 삽입, 매개변수 삽입
메시지, 메시지
getHeader(), 메시지 헤더에 액세스
메시지 헤더
액세스, 메시지 헤더에 액세스
메시지로
MIME 유형, In message의 MIME 콘텐츠 유형 가져오기
방법, 구성 요소 메서드
비동기, 비동기 생산자
비동기 생산자
구현, 비동기 생산자 구현 방법
사용 가능, 교환 패턴 테스트
생산자, 생산자
createExchange(), 생산자 메서드
getEndpoint(), 생산자 메서드
process(), 생산자 메서드
동기, 동기 생산자
비동기, 비동기 생산자
설치, 구성 요소 설치 및 구성
소비자, 소비자
event-driven, 이벤트 중심 패턴, 구현 단계
Scheduled, 예약된 폴링 패턴, 구현 단계
스레드, 개요
폴링, 폴링 패턴, 구현 단계
속성 교환
액세스, 교환 액세스 권한을 래핑
스레드, 개요
액세스, 메시지 헤더에 액세스, 교환 액세스 권한을 래핑
유선 탭 패턴, System Management
유형 변환
런타임 프로세스, 유형 변환 프로세스
유형 변환기
worker, 컨트롤러 유형 변환기
검색 파일, TypeConverter 파일 만들기
구현 단계, 형식 변환기를 구현하는 방법
구현 주석 처리, 주석이 달린 컨버터 클래스 구현
컨트롤러, 컨트롤러 유형 변환기
패키지, 유형 변환기 패키지
인터페이스 정의, 끝점 인터페이스
정의, 구성 요소 인터페이스
컨트롤러, 컨트롤러 유형 변환기
패키지, 유형 변환기 패키지
폴링, 폴링 패턴, 구현 단계
프로세서, 프로세서 인터페이스
구현, 프로세서 인터페이스 구현

A

AsyncCallback, 비동기 처리
AsyncProcessor, 비동기 처리
auto-discovery
구성, 자동 검색 구성

D

DefaultComponent
createEndpoint(), URI 구문 분석
DefaultEndpoint, 이벤트 중심 끝점 구현
createExchange(), 이벤트 중심 끝점 구현
createPollingConsumer(), 이벤트 중심 끝점 구현
getCamelConext(), 이벤트 중심 끝점 구현
getComponent(), 이벤트 중심 끝점 구현
getEndpointUri(), 이벤트 중심 끝점 구현

E

endpoint, endpoint
createConsumer(), 끝점 방법
createExchange(), 끝점 방법
createPollingConsumer(), 끝점 방법
createProducer(), 끝점 방법
event-driven, 이벤트 중심 끝점 구현
getCamelContext(), 끝점 방법
getEndpointURI(), 끝점 방법
isLenientProperties(), 끝점 방법
isSingleton(), 끝점 방법
Scheduled, 예약된 폴링 끝점 구현
setCamelContext(), 끝점 방법
인터페이스 정의, 끝점 인터페이스
event-driven, 이벤트 중심 패턴, 구현 단계, 이벤트 중심 끝점 구현
exchange
기능 가능, 교환 패턴 테스트
사용 가능, 교환 패턴 테스트
ExchangeHelper, ExchangeHelper 클래스
getContentType(), In message의 MIME 콘텐츠 유형 가져오기
getMandatoryHeader(), 메시지 헤더에 액세스, 교환 액세스 권한을 래핑
getMandatoryInBody(), 교환 액세스 권한을 래핑
getMandatoryOutBody(), 교환 액세스 권한을 래핑
getMandatoryProperty(), 교환 액세스 권한을 래핑
isInCapable(), 교환 패턴 테스트
isOutCapable(), 교환 패턴 테스트
resolveEndpoint(), 끝점 확인

G

getCamelConext(), 이벤트 중심 끝점 구현
getCamelContext(), 끝점 방법
getComponent(), 이벤트 중심 끝점 구현
getContentType(), In message의 MIME 콘텐츠 유형 가져오기
getEndpoint(), 생산자 메서드
getEndpointURI(), 끝점 방법
getEndpointUri(), 이벤트 중심 끝점 구현
getExchangeId(), 교환 방법
getHeader(), 메시지 헤더에 액세스
getIn(), 메시지 헤더에 액세스, 교환 방법
getMandatoryHeader(), 메시지 헤더에 액세스, 교환 액세스 권한을 래핑
getMandatoryInBody(), 교환 액세스 권한을 래핑
getMandatoryOutBody(), 교환 액세스 권한을 래핑
getMandatoryProperty(), 교환 액세스 권한을 래핑
getOut(), 교환 방법
getPattern(), 교환 방법
getProperties(), 교환 방법
getProperty(), 교환 방법
getUnitOfWork(), 교환 방법

I

isInCapable(), 교환 패턴 테스트
isLenientProperties(), 끝점 방법
isOutCapable(), 교환 패턴 테스트
isSingleton(), 끝점 방법

R

removeProperty(), 교환 방법
resolveEndpoint(), 끝점 확인

S

Scheduled, 예약된 폴링 패턴, 구현 단계, 예약된 폴링 끝점 구현
ScheduledPollEndpoint, 예약된 폴링 끝점 구현
setCamelContext(), 끝점 방법
setExchangeId(), 교환 방법
setIn(), 교환 방법
setOut(), 교환 방법
setProperty(), 교환 방법
setUnitOfWork(), 교환 방법
Spring 구성, Spring에서 구성 요소 구성

T

TypeConverter, 유형 변환기 인터페이스
TypeConverterLoader, 유형 변환기 로더

U

useIntrospectionOnEndpoint(), 끝점 매개변수 삽입 비활성화

법적 공지

Copyright © 2023 Red Hat, Inc.
The text of and illustrations in this document are licensed by Red Hat under a Creative Commons Attribution–Share Alike 3.0 Unported license ("CC-BY-SA"). An explanation of CC-BY-SA is available at http://creativecommons.org/licenses/by-sa/3.0/. In accordance with CC-BY-SA, if you distribute this document or an adaptation of it, you must provide the URL for the original version.
Red Hat, as the licensor of this document, waives the right to enforce, and agrees not to assert, Section 4d of CC-BY-SA to the fullest extent permitted by applicable law.
Red Hat, Red Hat Enterprise Linux, the Shadowman logo, the Red Hat logo, JBoss, OpenShift, Fedora, the Infinity logo, and RHCE are trademarks of Red Hat, Inc., registered in the United States and other countries.
Linux® is the registered trademark of Linus Torvalds in the United States and other countries.
Java® is a registered trademark of Oracle and/or its affiliates.
XFS® is a trademark of Silicon Graphics International Corp. or its subsidiaries in the United States and/or other countries.
MySQL® is a registered trademark of MySQL AB in the United States, the European Union and other countries.
Node.js® is an official trademark of Joyent. Red Hat is not formally related to or endorsed by the official Joyent Node.js open source or commercial project.
The OpenStack® Word Mark and OpenStack logo are either registered trademarks/service marks or trademarks/service marks of the OpenStack Foundation, in the United States and other countries and are used with the OpenStack Foundation's permission. We are not affiliated with, endorsed or sponsored by the OpenStack Foundation, or the OpenStack community.
All other trademarks are the property of their respective owners.