以下代码不起作用:
原因:
我认为我追查原因是: http://community.jboss.org/thread/150988 =>本文说HornetQ使用弱引用。
我的问题: 为什么代码不运行? (我的代码运行时略有不同,但代码重复失败)。我的唯一猜测是,那个 以下参考:
private Connection connection = null;
private Session session = null;
private MessageProducer producer = null;
不被视为强有力的参考? (这导致了垃圾收集器移除了对象的事实......但是它们不是强有力的参考吗?
或者代码是否存在另一个问题(如上所述,如果我将所有内容复制到一个单独的方法中,代码运行正常。但如果我在下面使用Singleton方法代码不起作用...)另一个假设是它可能与ThreadLocal有关,但我只使用一个线程...
代码无法正常工作(已拆除):
public class JMSMessageSenderTest {
private static final Logger logger = Logger.getLogger(JMSMessageSenderTest.class);
private static JMSMessageSenderTest instance;
private Connection connection = null;
private Session session = null;
private MessageProducer producer = null;
private JMSMessageSenderTest() {
super();
}
public static JMSMessageSenderTest getInstance() throws JMSException {
if (instance==null) {
synchronized(JMSMessageSenderTest.class) {
if (instance==null) {
JMSMessageSenderTest instanceTmp = new JMSMessageSenderTest();
instanceTmp.initializeJMSConnectionFactory();
instance = instanceTmp;
}
} }
return instance;
}
private void createConnectionSessionQueueProducer() throws Exception {
try {
Queue queue = HornetQJMSClient.createQueue("testQueue");
connection = initializeJMSConnectionFactory();
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
producer = session.createProducer(queue);
connection.start();
} catch (Exception e) {
cleanupAfterError();
throw e;
}
}
private void cleanupAfterError() {
if (connection != null){
try{
connection.close();
}catch(JMSException jmse) {
logger.error("Closing JMS Connection Failed",jmse);
}
}
session = null;
producer = null;
}
public synchronized void sendRequest(String url) throws Exception {
if (connection==null) {
createConnectionSessionQueueProducer();
}
try {
//HERE THE EXCEPTION IS THROWN, at least when debugging
TextMessage textMessage = session.createTextMessage(url);
producer.send(textMessage);
} catch (Exception e) {
cleanupAfterError();
throw e;
}
}
private Connection initializeJMSConnectionFactory() throws JMSException{
Configuration configuration = ConfigurationFactory.getConfiguration(null, null);
Map<String, Object> connectionParams = new HashMap<String, Object>();
connectionParams.put(org.hornetq.core.remoting.impl.netty.TransportConstants.PORT_PROP_NAME, 5445);
connectionParams.put(org.hornetq.core.remoting.impl.netty.TransportConstants.HOST_PROP_NAME, "localhost");
TransportConfiguration transportConfiguration = new TransportConfiguration(NettyConnectorFactory.class.getName(), connectionParams);
ConnectionFactory connectionFactory = (ConnectionFactory) HornetQJMSClient.createConnectionFactoryWithoutHA(JMSFactoryType.CF, transportConfiguration);
// return connectionFactory.createConnection(login, password);
return connectionFactory.createConnection();
}
/**
* Orderly shutdown of all resources.
*/
public void shutdown() {
cleanupAfterError();
}
}
TestCode运行上面的代码
JMSMessageSenderTest jmsMessageSender = JMSMessageSenderTest.getInstance();
jmsMessageSender.sendRequest("www.example.com)");
jmsMessageSender.shutdown();
出现以下错误:
I'm closing a JMS connection you left open. Please make sure you close all JMS connections explicitly before letting them go out of scope!
The JMS connection you didn't close was created here:
java.lang.Exception
at org.hornetq.jms.client.HornetQConnection.<init>(HornetQConnection.java:152)
at org.hornetq.jms.client.HornetQConnectionFactory.createConnectionInternal(HornetQConnectionFactory.java:662)
at org.hornetq.jms.client.HornetQConnectionFactory.createConnection(HornetQConnectionFactory.java:121)
解决方案:
1。)你还必须保持对ConnectionFactory的引用(参见下面Clebert的答案)
private ConnectionFactory factory = null;
2。)此代码包含一个严重的隐藏错误(不容易发现): 我在构造函数和createConnectionSessionQueueProducer()方法中初始化了Connection。因此它将覆盖旧值并且(因为它是需要关闭的Ressource)将导致HornetQ然后将关闭的陈旧连接,然后将抛出错误。
非常感谢!马库斯
答案 0 :(得分:2)
HornetQ将在连接工厂发布时关闭连接工厂。
您需要保留连接工厂的参考。
答案 1 :(得分:1)
我也有类似的问题。但它不应该崩溃。你的实现看起来不错。但唯一的问题是你没有关闭JMS连接,而jMS连接又被hornetQ gc关闭了。
代码可能出错的一点是你只在异常后才调用cleanupAfterError()。在发布消息并且JMS连接处于空闲状态之后,您也应该调用相同的方法。由于您只是打开一个连接来发布消息,然后不关闭该连接,除非发生异常,Hornetq GC正在找到该对象并在抛出此错误时将其删除。
如果我错过了某些内容,请告诉我