JMS(Jboss Messaging)的一點使用心得(五)Spring擴展應用-可自動重連的JmsMessageListenerContainer

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]
發佈了29 篇原創文章 · 獲贊 1 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章