但是這樣做會產生一個問題,如果在網絡不穩定的情況下,Jboss錯誤的回收了一個有效的Client連接,而Client端
對此一無所知,只會傻傻的等待着一個再也不會到來的JMS消息......
以下是一個會自動重連的JmsMessageListenerContainer,實現原理就是在監聽器中增加了一個線程,會定期Check連接的有效性,如果發現連接無效,則自動重連JMS服務器。以下是代碼:
ExJmsMessageListenerContainer.java
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的配置文件中可以這樣配置
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]