2012-01-08 49 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