2009-08-26 61 views
7

我想通過Geronimo的JNDI查找QueueConnectionFactoryQueueQueue返回正常,但QueueConnectionFactory查找始終返回空值。它不會拋出NamingException,這是我所期望的,如果JNDI名稱不正確。爲什麼我的JNDI查找QueueConnectionFactory返回null?

任何人都可以看到我做錯了什麼?測試代碼下面的輸出:

 
true 
false 

import javax.jms.Queue; 
import javax.jms.QueueConnectionFactory; 
import javax.naming.InitialContext; 
import javax.naming.NamingException; 

public class JndiTest 
{ 
    private final static String QUEUE_NAME = "jca:/org.apache.geronimo.configs/activemq-ra/JCAAdminObject/SendReceiveQueue"; 
    private final static String FACTORY_NAME = "jca:/org.apache.geronimo.configs/activemq-ra/JCAManagedConnectionFactory/DefaultActiveMQConnectionFactory"; 

    public static void main(String[] args) throws NamingException 
    { 
     InitialContext ctx = new InitialContext(); 
     QueueConnectionFactory factory = (QueueConnectionFactory) ctx.lookup(FACTORY_NAME); 
     Queue queue = (Queue)ctx.lookup(QUEUE_NAME); 
     System.out.println(factory == null); 
     System.out.println(queue == null);  
    } 

} 

在情況下,它有差別:我已添加OpenEJB的客戶端 - 3.0.1.jar,Geronimo的ejb_3.0_spec-1.0.1.jar和ActiveMQ的-core-4.1.2-G20090207.jar到類路徑中,我的jndi.properties文件具有屬性:

 
java.naming.factory.initial = org.apache.openejb.client.RemoteInitialContextFactory 
java.naming.provider.url = ejbd://127.0.0.1:4201 

回答

12

不引發異常的原因是 - 訪問資源時出現ClassLoadException。

而之所以會出現這種情況,是因爲從ResourceManager調用的ClassLoader正在搜索類com.sun.jndi.url.jca.jcaURLContextFactory。

如果您將工廠名稱更改爲其他名稱,那麼您應該看到NamingException - 但在查找的情況下,對於諸如ClassNotFound/IllegalState之類的異常,不會引發異常。

因此需要分析ActiveMQ的依賴關係。 Update1:​​可能的原因之一是工廠對象只能在託管環境中實例化。你是否將你的代碼作爲應用程序客戶端運行?

UPDATE2:發現這種行爲的原因的一些其他指針:

OpenEJB的JNDI實現僅 暴露的EJB,沒有任何其他資源。 如果您有j2ee應用程序客戶端,並且 您希望使用jms,則需要在客戶端上部署activemq適配器 的副本 。然後,您可以使用 j2ee java:comp/env上下文來查找 你的東西。

發現這個ActiveMQ的上網站:

ActiveMQ的JNDI實現不說話的命名服務器。它是 一個簡化版本的JNDI客戶端,它只允許從一個JMS實例獲取主題和 隊列。因此,不必提供命名服務器地址,而必須提供JMS服務器地址。大多數JNDI實現使用java.naming.provider.url屬性來指定命名服務器的地址。 ActiveMQ使用brokerURL之一。反而使用java.naming.provider.url會導致ActiveMQ嘗試加載整個Broker。

查看更多關於如何Connect using JNDI

在說明中所使用的初始上下文工廠是:可以發現org.apache.activemq.jndi.ActiveMQInitialContextFactory

一些示例代碼與JNDI測試here

我寫了一個簡單的java客戶端 - 提供者下方的提示url是正在使用的brokerURL。

Properties props = new Properties();    
props.put(Context.INITIAL_CONTEXT_FACTORY, 
      "org.apache.activemq.jndi.ActiveMQInitialContextFactory"); 
    //props.put(Context.PROVIDER_URL,"vm://localhost");//Either this or below 
    props.put(Context.PROVIDER_URL,"tcp://localhost:65432"); 
    props.put("queue.SendReceiveQueue", 
     "org.apache.geronimo.configs/activemq-ra/JCAAdminObject/SendReceiveQueue"); 

    InitialContext context = new InitialContext(props); 
    QueueConnectionFactory connectionFactory = (QueueConnectionFactory)context.lookup 
                   ("ConnectionFactory"); 
    Queue q = (Queue) context.lookup("SendReceiveQueue"); 
    System.out.println("conn is : " + connectionFactory.getClass().getName()); 
    System.out.println("queue is : " + q.getQueueName()); 

此程序給出的輸出:

conn是:org.apache.activemq.ActiveMQConnectionFactory 隊列是:org.apache.geronimo.configs/ActiveMQ的-RA/JCAAdminObject/SendReceiveQueue

+0

哇。感謝您的深思熟慮的答案。 – 2009-11-17 20:05:48

0

有兩個參與者在這裏,你看在JNDI的東西。其他人不得不把它放在那裏。我不知道你的環境的具體情況,但我對這種問題的方法是

  • 探索命名空間 - 那裏有什麼?你有任何JNDI瀏覽工具嗎?
  • 在應該註冊到JNDI的服務的日誌中查看,是否會報告任何錯誤?
+0

Geronimo提供一個JNDI瀏覽工具,兩個JNDI名稱似乎都在那裏。在我的測試工具中更改名稱會產生NamingException,所以它必須找到* something *。 – 2009-08-26 10:18:32

+0

對,但是它發現了什麼,誰把它放在那裏?對我來說,所有這些都指向了JMS提供者而不是你的代碼。 – djna 2009-08-26 21:41:30

1

我有一個相當的配置Tomcat/Geronimo J2EE jar/Geronimo JMS Jar/ActiveMQ 4 而我對你的jndi.propertie文件有點困惑。 礦看起來像這樣:

java.naming.factory.initial = org.apache.activemq.jndi.ActiveMQInitialContextFactory

java.naming.provider.url = tcp://localhost:61616

connectionFactoryNames = connectionFactory , TopicConnectionFactory

最大的區別是obviousely,你的初始上下文是遠程的。除此之外,我必須提供一個connectionFactoryNames,或者我得到一個NamingException。

1

我不知道爲什麼,但對我來說,使用上下文無效。看起來消息已發送,但我的消費者的onMessage未被調用。

利用上下文來摔不例外,但不起作用:

import javax.jms.MessageProducer; 
import javax.jms.Session; 
import javax.jms.TextMessage; 
import javax.jms.Topic; 
import javax.jms.TopicConnection; 
import javax.jms.TopicConnectionFactory; 
import javax.jms.TopicSession; 

public class HelloClient { 

public static void main(String[] args) throws Exception { 
    Properties ppt2 = new Properties(); 
    ppt2.put(Context.INITIAL_CONTEXT_FACTORY, 
      "org.apache.activemq.jndi.ActiveMQInitialContextFactory"); 
    ppt2.put(Context.PROVIDER_URL, "tcp://localhost:61616"); 
    ppt2.put("topic.MessageDestinationTopic", "console.jms/TopicQueue/JCAAdminObject/MessageDestinationTopic"); 
    Context ctx2 = new InitialContext(ppt2); 

    TopicConnectionFactory factory = (TopicConnectionFactory) ctx2.lookup("ConnectionFactory"); 
    TopicConnection connection = factory.createTopicConnection(); 
    TopicSession session = connection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE); 
    Topic topic = (Topic) ctx2.lookup("MessageDestinationTopic"); 

    MessageProducer producer = session.createProducer(topic); 

    TextMessage msg = session.createTextMessage(); 
    msg.setText("this is a test message"); 
    producer.send(msg); 
    producer.close(); 
    session.close(); 
    System.out.println("Message published. Please check application server's console to see the response from MDB"); 
    ctx2.close(); 
    System.exit(0); 

} 

} 

使用下面的代碼(沒有上下文)效果很好:

import javax.jms.MessageProducer; 
import javax.jms.Session; 
import javax.jms.TextMessage; 
import javax.jms.Topic; 
import javax.jms.TopicConnection; 
import javax.jms.TopicConnectionFactory; 
import javax.jms.TopicSession; 

public class HelloClient { 

    public static void main(String[] args) throws Exception { 

     TopicConnectionFactory factory = new org.apache.activemq.ActiveMQConnectionFactory("tcp://localhost:61616"); 
     TopicConnection connection = factory.createTopicConnection(); 
     TopicSession session = connection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE); 
     Topic topic = session.createTopic("MessageDestinationTopic"); 

     MessageProducer producer = session.createProducer(topic); 

     TextMessage msg = session.createTextMessage(); 
     msg.setText("this is a test message"); 
     producer.send(msg); 
     producer.close(); 
     session.close(); 
     System.out.println("Message published. Please check application server's console to see the response from MDB"); 
     System.exit(0); 

    } 

}