Java MessageListener未侦听Oracle队列中的消息
我已经实现了Oracle高级队列&我正在编写一个侦听程序。以下是我的样本:Java MessageListener未侦听Oracle队列中的消息,java,jakarta-ee,jms,advanced-queuing,Java,Jakarta Ee,Jms,Advanced Queuing,我已经实现了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.Exc
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队列中的消息
不幸的是,当我为这个类文件创建一个jar并运行它时,它只是运行然后退出并只消耗队列中的一条消息。为什么侦听器不继续运行&侦听队列
我以为它会继续侦听并检索队列中的所有消息,然后永远保持侦听模式,但它的行为不是这样的
如果有人能告诉我出了什么问题,我将不胜感激
感谢下面是另一个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();
}
这都是因为您在启动后立即关闭了连接/会话。您需要该进程启动一个守护进程线程,该线程在JVM中永远运行。JMS不负责保持JVM运行。您需要创建一个刚刚休眠的线程来完成此任务。尝试将所有代码从Try块的开头包装到块的结尾,并保留一段时间(true),以便在它使用消息后,再次运行所有队列设置并等待另一条消息。我认为您可能必须在处理每条消息之后创建该会话,因为它是主会话。这可能不是永久的解决方案,但它可能暂时还可以。@Logan,你指的是哪个try block?是主方法的吗?是的,对不起。在main方法中,我会把它放在Queue Queue之前,在main方法中的catch块之后,基本上包装所有代码。只是想看看它是否一开始运行不止一次,然后你就可以确定是否有任何代码可以被提取出来并且只执行一次。如果我把这个while循环放进去,需要CPU吗???当队列中没有消息时会发生什么?需要CPU吗?我不这么认为。您可以查看流程监视器以查看流程是否执行任何操作,但这几乎是任何流程都执行的操作。我认为当您设置侦听器时,代码会在此时等待消息,但实际上并没有完成while循环。您的问题是,一旦消息传入,它将运行其余代码并关闭。这个循环应该重置监听器,这样一旦它处理完,就可以进行另一个循环了。我能够在不使用while循环的情况下检索队列中的所有消息。我刚刚对Consumer.close()、session.close()和Qcon.close()行进行了注释&它现在可以工作了。但问题是它是否正确&我如何知道它占用了多少内存?有一个很好的工具可以监视javajkd中包含的任何java进程。它叫jconsole。如果你在程序运行时启动它,你可以连接到进程,查看它在运行时使用了多少内存和cpu。一旦创建了线程,它应该什么时候进入睡眠状态?你能为我的上述代码提供一个例子吗?