5.6. JMS
메시징 지원은 JBoss EAP Messaging(ActiveMQ Artemis) 하위 시스템과 통합된 JMS 구성 요소를 통해 제공됩니다.
JBoss Generic JMS 리소스 어댑터를 사용하여 벤더별 리소스 어댑터의 구성을 통해 또는 사용할 수 없는 경우 다른 JMS 구현과 통합할 수 있습니다.
5.6.1. JBoss EAP JMS 구성
표준 JBoss EAP XML 구성 파일을 통해 JBoss EAP 메시징 하위 시스템을 구성할 수 있습니다. 예를 들면 standalone.xml 또는 domain.xml입니다.
예를 들어 메모리 인스턴스에서 포함된 ActiveMQ Artemis를 사용합니다. 먼저 jms-destinations 섹션에 다음 XML 구성을 추가하여 메시징 하위 시스템에서 새 JMS 큐를 구성합니다.
<jms-queue name="WildFlyCamelQueue"> <entry name="java:/jms/queue/WildFlyCamelQueue"/> </jms-queue>
또는 CLI 스크립트를 사용하여 큐를 추가할 수도 있습니다.
$ jms-queue add --queue-address=WildFlyCamelQueue --entries=queue/WildFlyCamelQueue,java:/jms/queue/WildFlyCamelQueue
또한 사용자 지정 jms.xml 배포 설명자 내에 messaging-deployment
구성을 생성할 수 있습니다. 자세한 내용은 JBoss EAP 메시징 하위 시스템 설명서의 'jms.xml 파일' 섹션을 참조하십시오.
5.6.2. Camel 경로 구성
다음 JMS 생산자 및 소비자 예제는 JBoss EAP의 포함된 ActiveMQ Artemis 서버를 사용하여 대상에 메시지를 게시하고 사용합니다.
이 예제에서는 camel-cdi 구성 요소와 함께 CDI를 사용합니다. JMS ConnectionFactory 인스턴스는 JNDI 조회를 통해 Camel RouteBuilder에 삽입됩니다.
5.6.2.1. JMS Producer
DefaultJMSConnectionFactory
연결 팩토리가 JNDI의 RouteBuilder에 삽입됩니다. JBoss EAP XML 구성에서 메시징 하위 시스템 내에서 연결 팩토리를 찾을 수 있습니다.
다음으로 타이머 끝점은 10초마다 실행되어 이전에 구성된 WildFlyCamelQueue 대상에 XML 페이로드를 보냅니다.
@Startup @ApplicationScoped @ContextName("jms-camel-context") public class JmsRouteBuilder extends RouteBuilder { @Resource(mappedName = "java:jboss/DefaultJMSConnectionFactory") private ConnectionFactory connectionFactory; @Override public void configure() throws Exception { JmsComponent component = new JmsComponent(); component.setConnectionFactory(connectionFactory); getContext().addComponent("jms", component); from("timer://sendJMSMessage?fixedRate=true&period=10000") .transform(constant("<?xml version='1.0><message><greeting>hello world</greeting></message>")) .to("jms:queue:WildFlyCamelQueue") .log("JMS Message sent"); } }
JMS 메시지가 WildFlyCamelQueue 대상에 추가될 때마다 로그 메시지가 콘솔에 출력됩니다. 메시지가 큐에 실제로 배치되었는지 확인하려면 JBoss EAP 관리 콘솔을 사용할 수 있습니다.
5.6.2.2. JMS 소비자
JMS 메시지를 사용하기 위해 Camel RouteBuilder 구현은 생산자 예제와 유사합니다.
이전과 마찬가지로, 연결 팩토리는 JNDI에서 검색되고 JMSComponent 인스턴스에 삽입 및 설정됩니다.
JMS 끝점에서 WildFlyCamelQueue 대상의 메시지를 사용하면 콘텐츠가 콘솔에 기록됩니다.
@Override public void configure() throws Exception { JmsComponent component = new JmsComponent(); component.setConnectionFactory(connectionFactory); getContext().addComponent("jms", component); from("jms:queue:WildFlyCamelQueue") .to("log:jms?showAll=true"); }
5.6.2.3. JMS 트랜잭션
Camel JMS 경로가 JMS 트랜잭션에 참여할 수 있도록 하려면 몇 가지 추가 구성이 필요합니다. camel-jms는 Spring-jms를 기반으로 빌드되었으므로 JBoss EAP의 트랜잭션 관리자 및 연결 팩토리에서 작업할 수 있도록 일부 Spring 클래스를 구성해야 합니다. 다음 코드 예제에서는 CDI를 사용하여 트랜잭션 JMS Camel 경로를 구성하는 방법을 보여줍니다.
camel-jms 구성 요소에는 org.springframework. Cryostat.PlatformTransactionManager
유형의 트랜잭션 관리자가 필요합니다. 따라서 JtaTransactionManager
를 확장한 빈을 생성하여 시작합니다. 8080에 @Named
주석이 추가되어, 8080이 Camel 8080 레지스트리 내에 등록될 수 있습니다. 또한 JBoss EAP 트랜잭션 관리자 및 사용자 트랜잭션 인스턴스는 CDI를 사용하여 삽입됩니다.
@Named("transactionManager") public class CdiTransactionManager extends JtaTransactionManager { @Resource(mappedName = "java:/TransactionManager") private TransactionManager transactionManager; @Resource private UserTransaction userTransaction; @PostConstruct public void initTransactionManager() { setTransactionManager(transactionManager); setUserTransaction(userTransaction); } }
다음으로 사용하려는 트랜잭션 정책을 선언해야 합니다. 다시 @Named
주석을 사용하여 Camel에서 빈을 사용할 수 있도록 합니다. 트랜잭션 관리자는 원하는 트랜잭션 정책을 사용하여 TransactionTemplate을 생성할 수 있도록 삽입됩니다. 이 인스턴스의 PROPAGATION_REQUIRED.
@Named("PROPAGATION_REQUIRED") public class CdiRequiredPolicy extends SpringTransactionPolicy { @Inject public CdiRequiredPolicy(CdiTransactionManager cdiTransactionManager) { super(new TransactionTemplate(cdiTransactionManager, new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_REQUIRED))); } }
이제 Camel RouteBuilder 클래스를 구성하고 Camel JMS 구성 요소에 필요한 종속성을 삽입할 수 있습니다. JBoss EAP XA 연결 팩토리는 이전에 구성한 트랜잭션 관리자와 함께 삽입됩니다.
이 예에서 RouteBuilder는 queue1에서 메시지를 사용할 때마다 queue2라는 다른 JMS 큐로 라우팅됩니다. queue2에서 사용되는 메시지로 인해 JMS 트랜잭션이 rollback() DSL 메서드를 사용하여 롤백됩니다. 이로 인해 원본 메시지가 dead letter queue(DLQ)에 배치됩니다.
@Startup @ApplicationScoped @ContextName("jms-camel-context") public class JMSRouteBuilder extends RouteBuilder { @Resource(mappedName = "java:/JmsXA") private ConnectionFactory connectionFactory; @Inject CdiTransactionManager transactionManager; @Override public void configure() throws Exception { // Creates a JMS component which supports transactions JmsComponent jmsComponent = JmsComponent.jmsComponentTransacted(connectionFactory, transactionManager); getContext().addComponent("jms", jmsComponent); from("jms:queue:queue1") .transacted("PROPAGATION_REQUIRED") .to("jms:queue:queue2"); // Force the transaction to roll back. The message will end up on the Wildfly 'DLQ' message queue from("jms:queue:queue2") .to("log:end") .rollback(); }
5.6.2.4. 원격 JMS 대상
하나의 JBoss EAP 인스턴스는 원격 JNDI 를 통해 다른 JBoss EAP 인스턴스에 구성된 ActiveMQ Artemis 대상에 메시지를 보낼 수 있습니다.
이를 위해서는 몇 가지 추가 JBoss EAP 구성이 필요합니다. 먼저 내보낸 JMS 큐가 구성됩니다.
java:jboss/exported
네임스페이스에 바인딩된 JNDI 이름만 원격 클라이언트의 후보로 간주되므로 큐의 이름은 적절하게 지정됩니다.
JBoss EAP 클라이언트 애플리케이션 서버 및JBoss EAP 원격 서버에서 큐를 구성해야 합니다.
<jms-queue name="RemoteQueue"> <entry name="java:jboss/exported/jms/queues/RemoteQueue"/> </jms-queue>
클라이언트가 원격 서버에 연결하려면 사용자 액세스 자격 증명을 구성해야 합니다. 원격 서버에서 add user 유틸리티 를 실행하여 'guest' 그룹 내에 새 애플리케이션 사용자를 생성합니다. 이 예제에는 이름이 'admin'이고 암호가 'secret'인 사용자가 있습니다.
RouteBuilder 구현은 이전 예제와 다릅니다. 연결 팩토리를 삽입하는 대신 InitialContext를 구성하고 JNDI에서 직접 검색해야 합니다.
configureInitialContext
메서드는 이 InitialContext를 생성합니다. 원격 JBoss EAP 인스턴스 호스트 이름과 포트 번호를 참조해야 하는 공급자 URL을 설정해야 합니다. 이 예제에서는 JBoss EAP JMS http-connector를 사용하지만 여기에 설명된 대안이 있습니다.
마지막으로 경로는 10초마다 구성된 원격 대상인 'RemoteQueue'로 XML 페이로드를 전송하도록 구성됩니다.
@Override public void configure() throws Exception { Context initialContext = configureInitialContext(); ConnectionFactory connectionFactory = (ConnectionFactory) initialContext.lookup("java:jms/RemoteConnectionFactory"); JmsComponent component = new JmsComponent(); component.setConnectionFactory(connectionFactory); getContext().addComponent("jms", component); from("timer://foo?fixedRate=true&period=10000") .transform(constant("<?xml version='1.0><message><greeting>hello world</greeting></message>")) .to("jms:queue:RemoteQueue?username=admin&password=secret") .to("log:jms?showAll=true"); } private Context configureInitialContext() throws NamingException { final Properties env = new Properties(); env.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFactory"); env.put(Context.PROVIDER_URL, System.getProperty(Context.PROVIDER_URL, "http-remoting://my-remote-host:8080")); env.put(Context.SECURITY_PRINCIPAL, System.getProperty("username", "admin")); env.put(Context.SECURITY_CREDENTIALS, System.getProperty("password", "secret")); return new InitialContext(env); }
5.6.3. 보안
JMS 보안 섹션을 참조하십시오.
5.6.4. EAP의 Fuse 빠른 시작 예
빠른 시작 예제는 빠른 시작/camel/camel-jms 디렉터리에 있는 EAP 설치의
Fuse에서 사용할 수 있습니다.