Jboss为了保证运行效率,会对挂在它上面的JMSClient连接执行CallBack操作;如果发现该连接已经断掉(有个超时时间,可设置),则会回收该Client的JMS连接,以保证其他Client能及时地拿到JMS连接。
但是这样做会产生一个问题,如果在网络不稳定的情况下,Jboss错误的回收了一个有效的Client连接,而Client端
对此一无所知,只会傻傻的等待着一个再也不会到来的JMS消息......
以下是一个会自动重连的JmsMessageListenerContainer,实现原理就是在监听器中增加了一个线程,会定期Check连接的有效性,如果发现连接无效,则自动重连JMS服务器。以下是代码:
ExJmsMessageListenerContainer.java
package
jms.receiver;

import
javax.jms.Connection;
import
javax.jms.JMSException;
import
javax.jms.Session;

import
org.springframework.jms.listener.serversession.ServerSessionMessageListenerContainer;

/**
* @see ServerSessionMessageListenerContainer
*/
public
class
ExJmsMessageListenerContainer
extends
ServerSessionMessageListenerContainer
{

/** sharedMonitor */
private final Object sharedMonitor = new Object();

/** interval */
private long interval = 300000;

/** sleepTime */
private boolean isConnectionCheck = false;

/** JMS Connection Check Thread */
private CheckConnectionThread checker;

/** resetFlg */
private boolean resetFlg = false;

public void setInterval(long interval) {
this.interval = 60000 * interval;
}

public void setConnectionCheck(boolean isConnectionCheck) {
this.isConnectionCheck = isConnectionCheck;
}

@Override
protected void doStart() throws JMSException {
super.doStart();

if (this.isConnectionCheck) {

synchronized (this.sharedMonitor) {
if (!this.resetFlg) {
if (this.checker != null) {
this.checker.stop();

try {
Thread.sleep(this.interval);
} catch (InterruptedException e) {
this.logger.debug(e.getMessage(), e);
}
}

this.checker = new CheckConnectionThread();
new Thread(this.checker).start();
}
}
}
}

@Override
protected void doShutdown() throws JMSException {
synchronized (this.sharedMonitor) {
if (!this.resetFlg && this.checker != null) {
this.checker.stop();
}
}

super.doShutdown();
}

private boolean checkConnect() {
try {
Connection connection = this.getSharedConnection();
Session session = createSession(connection);
session.close();
session = null;
} catch (Exception e) {
this.logger.error("JMS Connection Error. [" + e.getMessage() + "]", e);
return false;
}

return true;
}

private boolean resetConnection() {
this.resetFlg = true;
try {
try {
destroy();
} catch (Exception e) {
this.logger.debug(e.getMessage(), e);
}
refreshSharedConnection();
setAutoStartup(true);
initialize();
} catch (Exception e) {
this.logger.error("Reset JMS Connection failed. [" + e.getMessage() + "]", e);
return false;
}

this.resetFlg = false;

this.logger.info("Reset JMS Connection success.");
return true;
}

private class CheckConnectionThread implements Runnable {

/** sleepTime */
private boolean checkRunFlg = true;

public void stop() {
this.checkRunFlg = false;
}

@Override
public void run() {
while (this.checkRunFlg) {
try {
Thread.sleep(ExJmsMessageListenerContainer.this.interval);
} catch (InterruptedException e) {
ExJmsMessageListenerContainer.this.logger.debug(e.getMessage(), e);
}
if (this.checkRunFlg && !checkConnect()) {
for (int i = 0; i < 3; i++) {
if (!this.checkRunFlg || resetConnection()) {
break;
}
try {
Thread.sleep(30000);
} catch (InterruptedException e) {
ExJmsMessageListenerContainer.this.logger.debug(e.getMessage(), e);
}
}
}
}
}

}
}
在Spring的配置文件中可以这样配置
<
bean
id
="exListenerContainerQueue"
lazy-init
="true"
class
="jms.receiver.ExJmsMessageListenerContainer"
>
<
property
name
="connectionFactory"
ref
="myConnectionFactory"
/>
<
property
name
="destinationName"
value
="B"
/>
<
property
name
="messageListener"
ref
="messageListener"
/>
<
property
name
="exceptionListener"
ref
="exceptionListener"
/>
<
property
name
="sessionTransacted"
value
="true"
/>
<
property
name
="connectionCheck"
value
="true"
/>
<
property
name
="interval"
value
="3"
/>
</
bean
>
其中,
connectionCheck是是否需要Check的Flag,
interval是Check的时间间隔,单位为“分”。
还有另外一种实现方式,请参见
[ http://blog.csdn.net/supersue/archive/2008/04/02/2244727.aspx]
但是这样做会产生一个问题,如果在网络不稳定的情况下,Jboss错误的回收了一个有效的Client连接,而Client端
对此一无所知,只会傻傻的等待着一个再也不会到来的JMS消息......
以下是一个会自动重连的JmsMessageListenerContainer,实现原理就是在监听器中增加了一个线程,会定期Check连接的有效性,如果发现连接无效,则自动重连JMS服务器。以下是代码:
ExJmsMessageListenerContainer.java















































































































































在Spring的配置文件中可以这样配置










还有另外一种实现方式,请参见
[ http://blog.csdn.net/supersue/archive/2008/04/02/2244727.aspx]