Jboss为了保证运行效率,会对挂在它上面的JMSClient连接执行CallBack操作;如果发现该连接已经断掉(有个超时时间,可设置),则会回收该Client的JMS连接,以保证其他Client能及时地拿到JMS连接。
但是这样做会产生一个问题,如果在网络不稳定的情况下,Jboss错误的回收了一个有效的Client连接,而Client端
对此一无所知,只会傻傻的等待着一个再也不会到来的JMS消息......
以下是一个会自动重连的JmsMessageListenerContainer,实现原理就是在监听器中增加了一个线程,会定期Check连接的有效性,如果发现连接无效,则自动重连JMS服务器。以下是代码:
ExJmsMessageListenerContainer.java
在Spring的配置文件中可以这样配置
其中,
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
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);
}
}
}
}
}
}
}
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 >
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 >
还有另外一种实现方式,请参见
[ http://blog.csdn.net/supersue/archive/2008/04/02/2244727.aspx]