2014-02-28 2 views
0

JMS 대기열에서 메시지를 읽는 경로를 Camel에 설정하려고합니다.Apache Camel JMS : "대기열에 연결할 때 대상을 만들 수 없습니다"

응용 프로그램에서 Tibco를 사용하고 여기에 데이터를 게시 할 수 없지만 팩터 리 및 대기열의 경로는/path/to/queueName : 형식 형식을 따르며 여기서 type은 qcf (대기열 연결 공장) 및 대기열. 나는 봄-DSL을 사용하고

는 XML은 다음과 같습니다 주목해야 할

12:41:19:385 - WARN - DefaultMessageListenerContainer - Setup of JMS message listener invoker failed for destination 'path/to/queue:queue' - trying to recover. Cause: Not allowed to create destination 
12:41:20:494 - INFO - DefaultMessageListenerContainer - Successfully refreshed JMS Connection 

한 가지입니다 : 응용 프로그램이 실행되는

<bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate"> 
    <property name="environment"> 
     <props> 
      <prop key="java.naming.factory.initial">...</prop> 
      <prop key="java.naming.provider.url">...LDAP Server URL...</prop> 
      <prop key="java.naming.referral">follow</prop> 
      <prop key="java.naming.security.credentials">...</prop> 
      <prop key="java.naming.security.principal">uid=...,ou=...,dc=...,dc=...</prop> 
     </props> 
    </property> 
</bean> 

<bean id="jmsQueueConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean"> 
    <property name="jndiTemplate" ref="jndiTemplate"/> 
    <property name="jndiName" value="/path/to/queueConnectionFactory:qcf"/> 
</bean> 

<bean id="authenticatedConnectionFactory" class="org.springframework.jms.connection.UserCredentialsConnectionFactoryAdapter"> 
    <property name="targetConnectionFactory" ref="jmsQueueConnectionFactory"/> 
    <property name="username" value="..."/> 
    <property name="password" value="..."/> 
</bean> 

<bean id="testjms" class="org.apache.camel.component.jms.JmsComponent"> 
    <property name="connectionFactory" ref="authenticatedConnectionFactory"/> 
</bean> 

<camelContext id="camelContext" xmlns="http://camel.apache.org/schema/spring"> 
    <route id="jmsRouteTest"> 
     <from uri="testjms:queue:/path/to/queue:queue" /> 
     <to uri="file:c:\inbox?fileName=jmsMessage.txt" /> 
    </route> 
</camelContext> 

동안 로그에 다음 줄을 던지는 유지 대상에 대한 첫 번째 슬래시 "/"가 사라지지만 URI에서 "queue :"를 제거하면 동일한 오류가 발생하지만 대상은 '/ path/to/queue : queue'가됩니다.

나는이 오류 검색 및 유래에 여기에 질문을 찾을 수있다 : Does anyone know exactly what javax.jms.InvalidDestinationException: Not allowed to create destination means?

그냥 구성이 맞는지 확인하기 위해, 나는 봄 XML에서 동일한 설정을 복사 다음 클래스를 (만들었습니다 클래스) :

import java.util.Properties; 

import javax.jms.JMSException; 
import javax.jms.Session; 
import javax.jms.TextMessage; 
import javax.jms.Queue; 
import javax.jms.QueueConnection; 
import javax.jms.QueueConnectionFactory; 
import javax.jms.QueueReceiver; 
import javax.jms.QueueSession; 

import javax.naming.Context; 
import javax.naming.InitialContext; 
import javax.naming.NamingException; 

import java.io.*; 

public class Test { 

public static void main(String[] args) throws Exception { 
    Properties properties = new Properties(); 

    properties.put("java.naming.provider.url", "...LDAP Server URL..."); 
    properties.put("java.naming.factory.initial", "..."); 
    properties.put("java.naming.referral", "follow"); 
    properties.put("java.naming.security.principal", "uid=...,ou=...,dc=...,dc=..."); 
    properties.put("java.naming.security.credentials", "..."); 
    properties.put("JmsConnectionFactory", "/path/to/queueConnectionFactory:qcf"); 
    properties.put("JmsDestinationName", "/path/to/queue:queue"); 
    properties.put("JmsUserName", "..."); 
    properties.put("JmsPassword", "..."); 

    Context context = null; 
    QueueConnection connection = null; 
    QueueSession session = null; 
    QueueReceiver receiver = null; 

    context = new InitialContext(properties); 

    Queue queue = (Queue) context.lookup((String) properties.get("JmsDestinationName")); 
    QueueConnectionFactory queueConnectionFactory = (QueueConnectionFactory) context.lookup((String) properties.get("JmsConnectionFactory")); 

    connection = queueConnectionFactory.createQueueConnection((String) properties.getProperty("JmsUserName"), 
                   properties.getProperty("JmsPassword")); 

    session = connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); 

    connection.start(); 

    receiver = session.createReceiver(queue); 

    while (true) { 
     TextMessage message = (TextMessage) receiver.receive(); 

     System.out.println("Received: " + message.getText()); 

     BufferedReader bufferRead = new BufferedReader(new InputStreamReader(System.in)); 
     String s = bufferRead.readLine(); 

     if ("b".equals(s)) { 
      break; 
     } 
    } 

    connection.close(); 
} 

} 

이 클래스에서는 대기열에있는 메시지를 읽을 수 있습니다.

이전에이 문제가 발생 했습니까?

자세한 정보가 필요한 경우 알려 주시기 바랍니다.

감사합니다.

답변

1

도움 주셔서 감사합니다. 그러나 해결책은 정말 간단했습니다.

디버그 할 소스 코드를 다운로드했고 DefaultMessageListenerContainer이라는 Spring 클래스에서 종료되었습니다. 세션에서 createConsumer 메소드가 호출되면 예외가 발생했습니다.

http://forum.spring.io/forum/spring-projects/integration/jms/129634-dbus-jms-message-listener-javax-jms-jmssecurityexception-not-permitted

는 기본적으로이 오류 JNDI를 방지하기 위해 대신 session.createQueue의 대상을 얻기 위해 사용하는 것을 말한다 봄 포럼에서 주제를 알려준().

는 그럼 난 엔드 포인트 URI의 JNDI 이름을 사용하는 방법을 검색하고 기본적으로 대상 해결이 필요하다는 것을 알 수 http://camel.465427.n5.nabble.com/JMS-queue-JNDI-instead-of-physical-name-td494620.html

을 발견했다. 그것을 추가하면 오류가 해결되었습니다.

<bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate"> 
    <property name="environment"> 
     <props> 
      <prop...</prop> 
     </props> 
    </property> 
</bean> 

<bean id="jmsQueueConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean"> 
    <property name="jndiTemplate" ref="jndiTemplate"/> 
    <property name="jndiName" value="..."/> 
</bean> 

<bean id="jmsDestinationResolver" class="org.springframework.jms.support.destination.JndiDestinationResolver"> 
    <property name="jndiTemplate" ref="jndiTemplate" /> 
    <property name="cache" value="true" /> 
</bean> 

<bean id="testjms" class="org.apache.camel.component.jms.JmsComponent"> 
    <property name="connectionFactory" ref="jmsQueueConnectionFactory"/> 
    <property name="destinationResolver" ref="jmsDestinationResolver" /> 
</bean> 

<camelContext id="camelContext" xmlns="http://camel.apache.org/schema/spring"> 
    <route id="testRoute"> 
     <from uri="testjms:jmsJNDIName?connectionFactory=jmsQueueConnectionFactory&amp;username=...&amp;password=..." /> 
     <to uri="file:C:\inbox" /> 
    </route> 
</camelContext> 

tl; dr - JNDI를 사용하여 대기열을 가져오고 대상 확인자를 지정합니다.

1

Tibco 메시지 브로커에서 먼저 대기열을 만들려면 Tibco 관리자가 필요합니다.

+0

내가 테스트 한 Java 클래스가 작동한다는 것을 잊어 버렸습니다. 나는 그 질문을 편집 할 것이다. 고맙습니다. –

0

createQueue 메서드의 이름이 잘못되었습니다.큐 자체를 실제로 만들 의도는 아니지만 이미 존재하는 큐를 참조하는 Queue 개체 만 있습니다 (Javadoc 참조).

JMS는 비 임시 대기열을 생성하는 API를 제공하지 않습니다. 따라서 다른 방법 (일반적으로 일부 관리 도구)으로 큐를 생성 한 다음 JNDI에서 큐를 찾아야합니다.

그러나 일부 JMS 공급자는 필요할 때이 메서드를 "잘못 사용하여"큐를 자동 생성하므로 다른 JMS 공급자가 이식 할 수 없습니다. 이것은 단지 JMS2.0에서 허용되는 documented이었습니다

+0

정말 유용한 정보입니다. 감사합니다. 나는 이것을 투표 할 것이지만 나는 명성이 필요하지 않다. –