簡體   English   中英

Apache Camel JMS:嘗試連接到隊列時“不允許創建目標”

[英]Apache Camel JMS: “Not allowed to create destination” when trying to connect to a queue

我正在嘗試在駱駝中設置一個從JMS隊列讀取消息的路由。

該應用程序使用Tibco,我不允許在此處發布任何數據,但是工廠和隊列的路徑遵循/ path / to / queueName:type的格式,其中type可以是qcf(隊列連接工廠)和queue 。

我正在使用Spring-DSL,XML是:

<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>

當應用程序運行時,它會在日志中不斷拋出以下行:

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

要注意的一件事是目標的第一個斜杠“ /”消失了,但是如果我從URI中刪除“ queue:”,則會發生相同的錯誤,但是目標變為“ / path / to / queue:queue”。

我已經搜索了該錯誤,並在stackoverflow上找到了一個問題: 有誰確切知道javax.jms.InvalidDestinationException是什么:不允許創建目標方法?

為了確保配置正確,我創建了以下類(將完全相同的設置從Spring 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();
}

}

通過此類,我可以讀取隊列中的消息。

有人遇到過這個問題嗎?

如果您需要更多信息,請告訴我。

謝謝。

聽起來您需要先讓一些Tibco管理員來在Tibco消息代理上創建該隊列。

謝謝您的幫助,但是解決方案非常簡單。

我已經下載了要調試的源代碼,並在名為DefaultMessageListenerContainer的Spring類中結束了該類,在會話中調用createConsumer方法時引發了異常。

這使我想到了Spring論壇中的一個主題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獲取隊列並指定目標解析器。

createQueue方法的名稱具有誤導性。 它並不是要真正創建隊列本身,而僅僅是引用一個已經存在的隊列的Queue對象(請參閱Javadoc )。

JMS不提供任何用於創建(非臨時)隊列的API。 這就是為什么您必須通過其他方式(通常是某些管理工具)創建隊列,然后在JNDI中進行查找的原因。

但是某些JMS提供程序“濫用”此方法在需要時自動創建隊列,從而使其無法移植到其他JMS提供程序。 這只是被記錄在JMS 2.0被允許

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM