9장. 트랜잭션을 사용하는 Camel 애플리케이션 작성
available-to-be-referenced 서비스 유형을 구성한 후 애플리케이션을 작성할 준비가 된 것입니다. 세 가지 유형의 서비스는 다음과 같습니다.
다음 인터페이스 중 하나를 구현하는 트랜잭션 관리자 한 개:
-
javax.transaction.UserTransaction
-
javax.transaction.TransactionManager
-
org.springframework.transaction.PlatformTransactionManager
-
-
javax.sql.DataSource
. 인터페이스를 구현하는 하나 이상의 JDBC 데이터 소스입니다. 종종 둘 이상의 데이터 소스가 있습니다. -
javax.jms.ConnectionFactory
인터페이스를 구현하는 하나 이상의 JMS 연결 팩토리입니다. 종종 하나 이상의 것이 있습니다.
이 섹션에서는 트랜잭션, 데이터 소스 및 연결 팩토리 관리와 관련된 Camel 관련 구성에 대해 설명합니다.
이 섹션에서는 SpringTransactionPolicy
와 같은 여러 가지 Spring 관련 개념에 대해 설명합니다. Camel 컨텍스트를 정의하는 XML 언어인 Spring XML DSL 과 블루프린트 XML DSL 사이에는 명확한 차이점이 있습니다. Spring XML DSL은 Fuse에서 더 이상 사용되지 않습니다. 그러나 Camel 트랜잭션 메커니즘은 내부적으로 Spring 라이브러리를 계속 사용합니다.
여기에 있는 대부분의 정보는 사용되는 PlatformTransactionManager
유형에 의존하지 않습니다. PlatformTransactionManager
가 Narayana 트랜잭션 관리자인 경우 전체 JTA 트랜잭션이 사용됩니다. PlatformTransactionManager
가 로컬 블루프린트 < bean
>로 정의된 경우 (예: org.springframework.jms.connection.JmsTransactionManager
) 로컬 트랜잭션이 사용됩니다.
트랜잭션 분리는 트랜잭션을 시작, 커밋, 롤백하는 절차를 나타냅니다. 이 섹션에서는 프로그래밍 및 구성에 의해 트랜잭션 분리를 제어하는 데 사용할 수 있는 메커니즘에 대해 설명합니다.
9.1. 경로를 표시하여 트랜잭션 분리
Apache Camel은 경로에서 트랜잭션을 시작하는 간단한 메커니즘을 제공합니다. transacted()
명령을 Java DSL에 삽입하거나 XML DSL에 < transacted/
> 태그를 삽입합니다.
그림 9.1. 경로를 표시하여 분리
트랜잭션된 프로세서는 다음과 같이 트랜잭션을 분류합니다.
- 교환이 트랜잭션된 프로세서에 들어가면 트랜잭션된 프로세서는 기본 트랜잭션 관리자를 호출하여 트랜잭션을 시작하고 현재 스레드에 트랜잭션을 연결합니다.
- 교환이 나머지 경로의 끝에 도달하면, 트랜잭션된 프로세서는 트랜잭션 관리자를 호출하여 현재 트랜잭션을 커밋합니다.
9.1.1. JDBC 리소스가 포함된 샘플 경로
그림 9.1. “경로를 표시하여 분리” 경로에 transacted()
DSL 명령을 추가하여 트랜잭션되는 경로의 예를 보여줍니다. transacted()
노드를 따르는 모든 경로 노드는 트랜잭션 범위에 포함됩니다. 이 예에서 다음 두 노드는 JDBC 리소스에 액세스합니다.
9.1.2. Java DSL의 경로 정의
다음 Java DSL 예제에서는 transacted()
DSL 명령으로 경로를 표시하여 트랜잭션 경로를 정의하는 방법을 보여줍니다.
import org.apache.camel.builder.RouteBuilder; class MyRouteBuilder extends RouteBuilder { public void configure() { from("file:src/data?noop=true") .transacted() .bean("accountService","credit") .bean("accountService","debit"); } }
이 예에서 파일 끝점은 한 계정에서 다른 계정으로 수신자 전송을 설명하는 일부 XML 형식 파일을 읽습니다. 첫 번째 Cryostat ()
호출 크레딧은 수혜자의 계정에 지정된 합계를 제공한 다음 두 번째 blank ()
호출에서 지정된 양의 비용을 보낸 사람의 계정에서 뺀 값입니다. 둘 다 useful()
호출을 수행하면 데이터베이스 리소스에 대한 업데이트가 수행됩니다. 데이터베이스 리소스가 트랜잭션 관리자를 통해 트랜잭션에 바인딩되는 것으로 가정합니다(예: 6장. JDBC 데이터 소스 사용 ).
9.1.3. 블루프린트 XML의 경로 정의
이전 경로는 블루프린트 XML로 표시될 수도 있습니다. & lt;transacted /
> 태그는 다음 XML과 같이 경로를 트랜잭션으로 표시합니다.
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ...> <camelContext xmlns="http://camel.apache.org/schema/blueprint"> <route> <from uri="file:src/data?noop=true" /> <transacted /> <bean ref="accountService" method="credit" /> <bean ref="accountService" method="debit" /> </route> </camelContext> </blueprint>
9.1.4. 기본 트랜잭션 관리자 및 트랜잭션 정책
트랜잭션을 분리하려면 트랜잭션된 프로세서가 특정 트랜잭션 관리자 인스턴스와 연결되어야 합니다. Transact ed()
를 호출할 때마다 트랜잭션 관리자를 지정해야 합니다. 변환된 프로세서는 합리적인 기본값을 자동으로 선택합니다. 예를 들어 구성에 트랜잭션 관리자 인스턴스가 하나만 있는 경우 거래된 프로세서는 암시적으로 이 트랜잭션 관리자를 선택하여 트랜잭션을 위임합니다.
트랜잭션된 프로세서는 전파 정책 및 트랜잭션 관리자를 캡슐화하는 TransactedPolicy
유형의 트랜잭션 정책으로 구성할 수도 있습니다(자세한 내용은 9.4절. “트랜잭션 전파 정책” 참조). 다음 규칙은 기본 트랜잭션 관리자 또는 트랜잭션 정책을 선택하는 데 사용됩니다.
org.apache.camel.spi.#159edPolicy
유형에 대해 하나의 8080만 있는 경우 이 8080을 사용합니다.참고CryostatedPolicy
유형은 9.4절. “트랜잭션 전파 정책” 에 설명된SpringTransactionPolicy
유형의 기본 유형입니다. 따라서 여기에 언급된 빈은SpringTransactionPolicy
8080이 될 수 있습니다.-
유형의 빈이 있는 경우
org.apache.camel.spi.#159edPolicy
ID
가 ,PROPAGATION_REQUIRED
인 경우 이 Cryostat를 사용합니다. -
org.springframework. Cryostat.PlatformTransactionManager
유형의 Cryostat가 하나뿐인 경우 이 8080을 사용하십시오.
또한 빈 ID를 transacted()
의 인수로 제공하여 8080을 명시적으로 지정하는 옵션도 있습니다. 9.4.4절. “Java DSL의 PROPAGATION_NEVER
정책이 포함된 샘플 경로”을 참조하십시오.
9.1.5. 트랜잭션 범위
트랜잭션 프로세서를 경로에 삽입하면 트랜잭션 관리자는 교환이 이 노드를 통과할 때마다 새 트랜잭션을 생성합니다. 트랜잭션 범위는 다음과 같이 정의됩니다.
- 트랜잭션은 현재 스레드와만 연결됩니다.
- 트랜잭션 범위는 트랜잭션된 프로세서를 따르는 모든 경로 노드를 포함합니다.
트랜잭션된 프로세서 앞에 있는 경로 노드는 트랜잭션에 없습니다. 그러나 경로가 트랜잭션 끝점으로 시작되면 경로의 모든 노드가 트랜잭션에 있습니다. 9.2.5절. “경로 시작 시 트랜잭션 끝점”을 참조하십시오.
다음 경로를 고려하십시오. transacted()
DSL 명령이 데이터베이스 리소스에 액세스하는 첫 번째 8080 () 호출
뒤에 실수로 표시되기 때문에 올바르지 않습니다.
// Java import org.apache.camel.builder.RouteBuilder; public class MyRouteBuilder extends RouteBuilder { ... public void configure() { from("file:src/data?noop=true") .bean("accountService", "credit") .transacted() // <-- WARNING: Transaction started in the wrong place! .bean("accountService", "debit"); } }
9.1.6. 트랜잭션 경로에 스레드 풀 없음
지정된 트랜잭션이 현재 스레드와만 연결되어 있음을 이해하는 것이 중요합니다. 새 스레드의 처리는 현재 트랜잭션 트랜잭션에 참여하지 않으므로 트랜잭션 경로 중간에 스레드 풀을 만들지 않아야 합니다. 예를 들어 다음 경로는 문제를 유발하도록 바인딩됩니다.
// Java import org.apache.camel.builder.RouteBuilder; public class MyRouteBuilder extends RouteBuilder { ... public void configure() { from("file:src/data?noop=true") .transacted() .threads(3) // WARNING: Subthreads are not in transaction scope! .bean("accountService", "credit") .bean("accountService", "debit"); } }
이전과 같은 경로는 threads()
DSL 명령이 트랜잭션된 경로와 호환되지 않기 때문에 데이터베이스가 손상될 수 있습니다. threads()
호출이 transacted()
호출보다 우선하더라도 경로가 예상대로 작동하지 않습니다.
9.1.7. 경로를 조각으로 분할
경로를 조각으로 분할하고 각 경로 조각이 현재 트랜잭션에 참여하도록 하려면 직접
엔드포인트를 사용할 수 있습니다. 예를 들어, 전송 양이 큰지(100보다) 작는지(100 미만) 작는지 여부에 따라 라우터 조각을 분리하기 위해 다음과 같이 choice()
DSL 명령 및 직접 끝점을 사용할 수 있습니다.
// Java import org.apache.camel.builder.RouteBuilder; public class MyRouteBuilder extends RouteBuilder { ... public void configure() { from("file:src/data?noop=true") .transacted() .bean("accountService", "credit") .choice().when(xpath("/transaction/transfer[amount > 100]")) .to("direct:txbig") .otherwise() .to("direct:txsmall"); from("direct:txbig") .bean("accountService", "debit") .bean("accountService", "dumpTable") .to("file:target/messages/big"); from("direct:txsmall") .bean("accountService", "debit") .bean("accountService", "dumpTable") .to("file:target/messages/small"); } }
직접 끝점이 동기이므로 direct:txbig
와 direct:tx
windows로 시작하는 조각과 현재 트랜잭션에 모두 참여합니다. 즉, 조각은 첫 번째 경로 조각과 동일한 스레드에서 실행되므로 동일한 트랜잭션 범위에 포함됩니다.
seda
끝점을 사용하여 경로 조각에 참여해서는 안 됩니다. Seda
소비자 끝점은 경로 조각(동기화 처리)을 실행하기 위한 새 스레드(또는 스레드)를 생성합니다. 따라서 조각은 원래 트랜잭션에 참여하지 않습니다.
9.1.8. 리소스 끝점
다음 Apache Camel 구성 요소는 경로의 대상으로 표시될 때 리소스 끝점 역할을 합니다(예: to()
DSL 명령에 표시되는 경우). 즉, 이러한 끝점은 데이터베이스 또는 영구 큐와 같은 트랜잭션 리소스에 액세스할 수 있습니다. 리소스 끝점은 현재 트랜잭션을 시작한 트랜잭션 프로세서와 동일한 트랜잭션 관리자와 연결된 경우 현재 트랜잭션에 참여할 수 있습니다.
- ActiveMQ
- AMQP
- Hibernate
- iBATIS
- JavaSpace
- JBI
- JCR
- JDBC
- JMS
- JPA
- LDAP
9.1.9. 리소스 끝점이 있는 샘플 경로
다음 예제에서는 리소스 끝점이 있는 경로를 보여줍니다. 이렇게 하면 두 개의 다른 JMS 큐로 금전 전송 순서를 보냅니다. 크레딧
대기열은 주문을 처리하여 수신자의 계정을 계산합니다. 직불 큐는
발신자의 계정을 끌기 위해 주문을 처리합니다. 해당 직불이 있는 경우에만 크레딧이 있어야 합니다. 결과적으로 큐에 있는 작업을 단일 트랜잭션으로 묶어야 합니다. 트랜잭션이 성공하면 신용 주문과 직불 순서가 모두 큐에 추가됩니다. 오류가 발생하면 주문이 큐에 추가되지 않습니다.
from("file:src/data?noop=true") .transacted() .to("jmstx:queue:credits") .to("jmstx:queue:debits");