2012-01-08 43 views
1

我已經實現了Oracle高級隊列&我在寫一個監聽器程序。下面是我的示例:MessageListener不在Oracle隊列中收聽消息

package com.myprog; 

import java.io.File; 
import java.io.FileInputStream; 
import java.io.StringWriter; 
import java.sql.Connection; 
import java.sql.DriverManager; 
import java.util.Properties; 

import javax.jms.ExceptionListener; 
import javax.jms.JMSException; 
import javax.jms.Message; 
import javax.jms.MessageConsumer; 
import javax.jms.MessageListener; 
import javax.jms.Queue; 
import javax.jms.QueueConnection; 
import javax.jms.QueueConnectionFactory; 
import javax.jms.Session; 
import javax.jms.TextMessage; 

import oracle.jms.AQjmsFactory; 
import oracle.jms.AQjmsSession; 

import org.apache.log4j.Logger; 

public class abc implements MessageListener, ExceptionListener { 
private static String queueUserName = "admin"; 
private static String queueName = "my_queue"; 

// Initialize the logger 
private static Logger log = Logger.getLogger(abc.class); 

public static void main(String[] args) { 
    final String METHOD_NAME = "main()"; 

    abc a = new abc();    

     Queue queue; 
     try { 
     QueueConnection QCon = getConnection(); 
     Session session = QCon.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); 
     QCon.start(); 

     queue = ((AQjmsSession) session).getQueue(queueUserName, queueName); 
     MessageConsumer consumer = session.createConsumer(queue);  

     consumer.setMessageListener(a); 
     QCon.setExceptionListener(a); 

     consumer.close(); 
     session.close(); 
     QCon.close(); 
     } catch (JMSException e) { 
     e.printStackTrace(); 
     }   

} 

public static QueueConnection getConnection() { 
    String hostname = "myhost"; 
    String oracle_sid = "mysid"; 
    int portno = 1521; 
    String userName = "myapp"; 
    String password = "pwd"; 
    String driver = "thin"; 
    QueueConnectionFactory QFac = null; 
    QueueConnection QCon = null; 
    try { 
    // get connection factory , not going through JNDI here 
    QFac = AQjmsFactory.getQueueConnectionFactory(hostname, oracle_sid, portno,driver); 

    // create connection 
    QCon = QFac.createQueueConnection(userName, password); 
    } catch (Exception e) { 
    e.printStackTrace(); 
    } 
    return QCon; 
} 

@Override 
public void onException(JMSException e) { 
    log.error(e);  
} 

@Override 
public void onMessage(Message message) { 
    TextMessage msg = (TextMessage) message; 

    try { 
     String m = msg.getText(); 
     System.out.println("m="+m); 
     log.info("MESSAGE RECEIVED " + m); 
    } catch (JMSException e) { 
     log.error(e); 
    } 
} 

}

請注意,此計劃是一個獨立的程序將繼續運行&聽在Oracle隊列中的消息。

不幸的是,當我創建這個類文件&來看,它的罐子,它只是運行&然後退出&在隊列中僅消耗1消息。爲什麼聽衆不能繼續在隊列中運行&?

我以爲它會繼續收聽&檢索隊列中的所有消息&然後將永遠保持在偵聽模式,但它不會那樣表現。

欣賞是否有人能告訴我發生了什麼問題。

感謝

+0

嘗試從try塊的開頭將所有代碼封裝到塊的末尾(true),這樣一旦它消耗了一條消息,它就會再次運行該隊列的所有設置,並且正在等待另一條消息。我認爲在處理每條消息之後,您可能必須創建該會話,因爲它處於主要狀態。這可能不是永久的解決方案,但現在可能會得到解決。 – Logan 2012-01-08 04:12:14

+0

@Logan,哪個嘗試塊是你指的?它是主要方法嗎? – Mike 2012-01-08 04:19:44

+0

是的,對不起。主要方法之一。 – Logan 2012-01-08 04:34:24

回答

0

下面是另一個例子JMS如何循環處理多個消息的示例。

Performs a JNDI lookup of the ConnectionFactory and Destination. 
Creates a Connection and a Session. 
Creates a MessageConsumer: 

consumer = session.createConsumer(dest); 
Starts the connection, causing message delivery to begin: 

connection.start(); 
Receives the messages sent to the destination until the end-of-message-stream control message is received: 

while (true) { 
    Message m = consumer.receive(1); 
    if (m != null) { 
    if (m instanceof TextMessage) { 
     message = (TextMessage) m; 
     System.out.println("Reading message: " + 
     message.getText()); 
    } else { 
     break; 
    } 
    } 
} 

Because the control message is not a TextMessage, the receiving program terminates the while loop and stops receiving messages after the control message arrives. 
Closes the connection in a finally block, automatically closing the session and MessageConsumer. 

你或許能夠在while循環中包裝這段代碼。這取決於JMS如何讓您處理連接和會話對象,以及它們是否自動關閉,但您可以嘗試包裝這一點。

while(true) { 
     QCon.start(); 

     queue = ((AQjmsSession) session).getQueue(queueUserName, queueName); 
     MessageConsumer consumer = session.createConsumer(queue);  

     consumer.setMessageListener(a); 
     QCon.setExceptionListener(a); 

     consumer.close(); 
} 
+0

你能告訴我在哪裏可以把while循環放在我的代碼中? – Mike 2012-01-08 04:21:01

+0

我會把它放在Queue隊列之前,並在主方法中的catch塊之後,基本上包裝所有的代碼。只要看看它是否一次運行多次,那麼在這之後你可以確定是否有任何代碼可以被取出並且只執行一次。 – Logan 2012-01-08 04:32:09

+0

如果我把這個while循環,它會佔用CPU嗎?隊列中沒有消息時會發生什麼?它會佔用CPU嗎? – Mike 2012-01-08 06:36:12

2

這都是因爲您在啓動後立即關閉連接/會話。 YOu需要進程啓動一個在JVM中永遠運行的守護進程線程。 JMS不負責保持JVM運行。你需要創建一個剛剛睡過的線程來完成這個任務。

+0

你能提供樣本代碼嗎? – Mike 2012-01-08 23:00:52

+0

線程一旦創建,它應該什麼時候進入睡眠?你能提供一個我上面的代碼的例子嗎? – Mike 2012-01-08 23:31:54

相關問題