2012-10-18 14 views
8

1.).netクライアントから、クライアントがサーバーに接続されている(つまり、送受信できる)かどうかをテストします。 tryブロックの中でメッセージを送信し、その後の例外をキャッチすることができますが、私はより洗練されたソリューションを望んでいます。Websphere MQの接続状態を取得する方法と接続をリセットする方法:

2)接続を開いたり、閉じたり、開いたりするにはどうすればよいですか?私が上記の質問1を解決しようとしたところで、私は接続を開いたときにconnection.Close()を呼び出すと、接続ファクトリから別の接続を取得できないことを発見しました。エラーメッセージXMSCC0008を受け取ります

私は非常に標準的なバニラMQ構成を使用しています。クライアントの接続方法は次のとおりです。

ISession session = MQAccess.GetSession(MQAccess.Connection); 
IDestination destination = session.CreateTopic(SubTopicName); 
Consumer = MQAccess.GetConsumer(session, destination); 
Consumer.MessageListener = new MessageListener(HandleMQSubEvent); 
MQAccess.Connection.Start(); 

ここで、MQAccessは小さなユーティリティクラスです。 MQClientに改名MQAccessクラス:

public static class MQAccess 
{ 
    public static readonly MQConfigurationSectionHandler ConfigSettings; 
    public static readonly IConnectionFactory ConnectionFactory; 

    private static readonly IConnection connection; 
    public static IConnection Connection 
    { 
     get { return connection; } 
    } 

    static MQAccess() 
    { 
     ConfigSettings = (MQConfigurationSectionHandler) 
      ConfigurationManager.GetSection("mq-configuration"); 

     XMSFactoryFactory factory = XMSFactoryFactory.GetInstance(XMSC.CT_WMQ); 
     ConnectionFactory = factory.CreateConnectionFactory(); 
     ConnectionFactory.SetStringProperty(XMSC.WMQ_HOST_NAME, ConfigSettings.Hostname); 
     ConnectionFactory.SetIntProperty(XMSC.WMQ_PORT, ConfigSettings.Port); 
     ConnectionFactory.SetStringProperty(XMSC.WMQ_CHANNEL, ConfigSettings.Channel); 

     if (ConfigSettings.QueueManager == string.Empty) 
     { 
      ConnectionFactory.SetStringProperty(XMSC.WMQ_QUEUE_MANAGER, ""); 
     } 
     else 
     { 
      ConnectionFactory.SetStringProperty(XMSC.WMQ_QUEUE_MANAGER, ConfigSettings.QueueManager); 
     } 

     connection = GetConnection(); 
    } 

    public static IConnection GetConnection() 
    { 
     return ConnectionFactory.CreateConnection(); 
    } 

    public static ISession GetSession(IConnection connection) 
    { 
     return connection.CreateSession(false, AcknowledgeMode.AutoAcknowledge); 
    } 

    public static IMessageProducer GetProducer(ISession session, IDestination destination) 
    { 
     return session.CreateProducer(destination); 
    } 

    public static IMessageConsumer GetConsumer(ISession session, IDestination destination) 
    { 
     return session.CreateConsumer(destination); 
    } 

    public static void MQPub(string TopicURI, string message) 
    { 
     using (var session = GetSession(Connection)) 
     { 
      using (var destination = session.CreateTopic(TopicURI)) 
      { 
       using (var producer = GetProducer(session, destination)) 
       { 
        producer.Send(session.CreateTextMessage(message)); 
       } 
      } 
     } 
    } 

    public static void MQPub(string TopicURI, IEnumerable<string> messages) 
    { 
     using (var session = GetSession(Connection)) 
     { 
      using (var destination = session.CreateTopic(TopicURI)) 
      { 
       using (var producer = GetProducer(session, destination)) 
       { 
        foreach (var message in messages) 
        { 
         producer.Send(session.CreateTextMessage(message)); 
        } 
       } 
      } 
     } 
    } 
} 

編集:

はMQAccessコードを追加するための質問を編集します。 Tロブの提案ごとにインスタンスクラスを作成しました。接続解除方法はまだ問題がここにある

public class MQClient : IDisposable 
{ 
    public MQConfigurationSectionHandler ConfigSettings { get; private set; } 
    public IConnectionFactory ConnectionFactory { get; private set; } 

    public IConnection Connection { get; private set; } 

    public IMessageConsumer Consumer { get; private set; } 
    public IMessageProducer Producer { get; private set; } 
    // Save sessions as fields for disposing and future subscription functionality 
    private ISession ProducerSession; 
    private ISession ConsumerSession; 
    public string SubTopicName { get; private set; } 
    public string PubTopicName { get; private set; } 
    public bool IsConnected { get; private set; } 
    public event Action<Exception> ConnectionError; 
    private Action<IMessage> IncomingMessageHandler; 

    public MQClient(string subTopicName, string pubTopicName, Action<IMessage> incomingMessageHandler) 
    { 
     // Dont put connect logic in the constructor. If we lose the connection we may need to connect again. 
     SubTopicName = subTopicName; 
     PubTopicName = pubTopicName; 
     IncomingMessageHandler = incomingMessageHandler; 
    } 

    public string Connect() 
    { 
     IsConnected = false; 
     string errorMsg = string.Empty; 

     ConfigSettings = (MQConfigurationSectionHandler) 
       ConfigurationManager.GetSection("mq-configuration"); 

     XMSFactoryFactory factory = XMSFactoryFactory.GetInstance(XMSC.CT_WMQ); 
     ConnectionFactory = factory.CreateConnectionFactory(); 
     ConnectionFactory.SetStringProperty(XMSC.WMQ_HOST_NAME, ConfigSettings.Hostname); 
     ConnectionFactory.SetIntProperty(XMSC.WMQ_PORT, ConfigSettings.Port); 
     ConnectionFactory.SetStringProperty(XMSC.WMQ_CHANNEL, ConfigSettings.Channel); 

     if (ConfigSettings.QueueManager == string.Empty) 
      ConnectionFactory.SetStringProperty(XMSC.WMQ_QUEUE_MANAGER, ""); 
     else 
      ConnectionFactory.SetStringProperty(XMSC.WMQ_QUEUE_MANAGER, ConfigSettings.QueueManager); 

     Connection = ConnectionFactory.CreateConnection(); 


     if (!string.IsNullOrEmpty(PubTopicName)) 
     { 
      ProducerSession = Connection.CreateSession(false, AcknowledgeMode.AutoAcknowledge); 
      Producer = ProducerSession.CreateProducer(ProducerSession.CreateTopic(PubTopicName)); 
     } 

     if (!string.IsNullOrEmpty(SubTopicName) && IncomingMessageHandler != null) 
     { 
      ConsumerSession = Connection.CreateSession(false, AcknowledgeMode.AutoAcknowledge); 
      Consumer = ConsumerSession.CreateConsumer(ConsumerSession.CreateTopic(SubTopicName)); 
      Consumer.MessageListener = new MessageListener(IncomingMessageHandler); 
     } 

     try 
     { 
      Connection.Start(); 
      Connection.ExceptionListener = new ExceptionListener(ConnectionExceptionHandler); 
      IsConnected = true; 
     } 
     catch (TypeInitializationException ex) 
     { 
      errorMsg = "A TypeInitializationException error occured while attempting to connect to MQ. Check the Queue configuration in App.config. The error message is: " + ex.Message; 
     } 
     catch (IllegalStateException ex) 
     { 
      errorMsg = "An IllegalStateException error occured while attempting to connect to MQ. Check the Queue configuration in App.config. The error message is: " + ex.Message; 
     } 

     return errorMsg; 
    } 

    public void Disconnect() 
    { 
     if (Producer != null) 
     { 
      Producer.Close(); 
      Producer.Dispose(); 
      Producer = null; 
     } 

     if (ProducerSession != null) 
     { 
      // Call Unsubscribe here if subscription is durable 

      ProducerSession.Close(); 
      ProducerSession.Dispose(); 
      ProducerSession = null; 
     } 

     if (Connection != null) 
     { 
      Connection.Stop(); 

      //if (Connection.ExceptionListener != null) 
      // Connection.ExceptionListener = null; 

      // Per Shashi............ 
      //if (Consumer.MessageListener != null) 
      // Consumer.MessageListener = null; 

      Connection.Close(); 
      Connection.Dispose(); 
      Connection = null; 
     } 

     if (Consumer != null) 
     { 

      if (Consumer.MessageListener != null) 
       Consumer.MessageListener = null; 

      Consumer.Close(); 
      Consumer.Dispose(); 
      Consumer = null; 
     } 


     if (ConsumerSession != null) 
     { 
      // Call Unsubscribe here if subscription is durable 
      ConsumerSession.Close(); 
      ConsumerSession.Dispose(); 
      ConsumerSession = null; 
     } 

     IsConnected = false; 
    } 


    public void Publish(string message) 
    { 
     Producer.Send(ProducerSession.CreateTextMessage(message)); 
    } 


    public void Publish(string[] messages) 
    { 
     foreach (string msg in messages) 
      Publish(msg); 
    } 

    public void ConnectionExceptionHandler(Exception ex) 
    { 
     Disconnect(); // Clean up 

     if (ConnectionError != null) 
      ConnectionError(ex); 
    } 

    #region IDisposable Members 
    private bool disposed; 

    public void Dispose() 
    { 
     Dispose(true); 
     GC.SuppressFinalize(this); 
    } 

    protected virtual void Dispose(bool disposing) 
    { 
     if (!this.disposed) 
     { 
      if (disposing) 
       Disconnect(); 

      disposed = true; 
     } 
    } 
    #endregion 

} 

答えて

8

上記のエラーMSGのでクラッシュ - >where MQAccess is a small utility class.

質問の最初の部分は、接続がアクティブであるかどうか見分ける方法尋ねます。 WebSphere MQのXMSクラスは、Java以外のプラットフォーム用のJMS仕様の実装です。 JMS仕様にはかなり厳密に従っており、JMS仕様には接続またはセッションのメソッドがisConnectedと等価でないため、XMSもそうではありません。ただし、すべてのGETおよびPUTアクティビティは、JMS例外をキャッチするためにtry/catchブロック内で発生する必要があります。 (そこからはいつもlinkedExceptionを印刷します)JMS例外がスローされると、アプリケーションはそれを致命的とみなして処理します。そうしないと、Connection Factory以外のすべてのJMSオブジェクトが閉じられ、接続シーケンスを駆動します。問題の新しい情報に基づいて

UPDATE:
MQAccessクラスを投稿してくれてありがとう。これにより、何が起こっているかについてのかなりの洞察が得られますが、パート2のように接続が閉じて再オープンされたことを示すコードはまだありません。

ただし、コードは、クラスのインスタンスが構築されるようMQAccessクラス次いでMQAccess.GetConnectionとして公に露出させ、ICONNECTION connectionのプライベートインスタンスを作成することを示しています。現在公開されているMQAccessクラスには、connectionが保持する接続ハンドルを置き換える公開クラスまたは非公開クラスメソッドがありません。MQAccess.Connection.Close()が呼び出された場合、IConnectionオブジェクトインスタンスはMQAccessクラス内に永久に無効な接続ハンドルを保持します。接続が閉じられると、MQAccessのインスタンスは事実上無効になります。新しい接続を取得するには、MQAccessを削除して再インスタンス化する必要があります。

MQAccessクラスでは接続ファクトリが公開されているため、理論的には元のクラスを閉じた後でもをクラス外から呼び出して有効な新しいIConnectionオブジェクトを取得することができます。ただし、そのインスタンスはMQAccessクラスの範囲外に存在するため、その後のMQAccessの呼び出しは、そのクラスの外部で作成された新しい接続インスタンスではなく、無効なインスタンス変数connectionを参照します。

接続を閉じて再作成する必要がある場合は、内部からMQAccessを管理することを検討してください。低技術のアプローチでは、既存の接続を閉じる接続のためにMQAccess.Close()メソッドを記述し、すぐにconnection = GetConnection();を呼び出して、専用のconnection変数に常に有効な接続ハンドルが保持されるようにすることがあります。

これで問題が解決しない場合は、接続を終了して再作成するコードを投稿してください。

ところで、ネットワーク接続を介した非トランザクションセッションは、WMQを含むJMSプロバイダのメッセージを失うか重複させる可能性があります。これはあなたが意図したものでしたか?私はこれがなぜ他のSO投稿hereにあるのか説明しました。

+0

ありがとうTロブこれは本当に役に立ちます。あなたは正しいです - クラスはcontstructorでMQを開始すべきではありません。 linkedExceptionはどういう意味ですか? – Sam

+0

JMS例外(したがってJMSをモデル化しているのでXMS例外)は複数レベルの構造です。 JMSでは、トップレベルには「接続に失敗しました」などの一般的な例外が含まれますが、後続のレベルには「QMgrが見つかりません」または「間違ったQMgr名」などのプロバイダ固有のデータが含まれています。リンクされた例外が存在する場合は、おそらく診断に役立つ情報があります。 ['LinkedException'を参照してください。(http://pic.dhe.ibm.com/infocenter/wmqv7/v7r5/topic/com.ibm.mq.msc.doc/sapiexcpt.html#sapiexcpt_getlkex) –

+0

ああ、私は見ていないそのlinkedExceptionはIllegalStateExceptionのプロパティです。 – Sam

5

T.Robからのコメントへの追加。

質問1:
MQAccessのソースコードにアクセスしていただければ幸いです。はいの場合、接続がアクティブであるかどうかを示すプロパティーをMQAccessに公開することができます。アクセス権がない場合は、そのクラスの作成者にこのプロパティを追加するよう依頼する必要があります。プロパティを設定/リセットするには、次の操作を行います。

1)のcreateConnectionメソッドが正常に返された後にプロパティを設定します。
2)接続の例外リスナーを設定します。
3)例外ハンドラのプロパティをリセットします。理由コードをチェックし、接続が壊れている場合はプロパティをリセットします(XMSWMQ1107およびリンク例外にはMQRC 2009が含まれます)。

質問2
closingreopeningの接続方法を教えてください。接続を閉じるための私の推奨は:
1)まず接続を行います。停止()。
2)メッセージリスナーを削除します。基本的にconsumer.MessageListener = nullを実行します。
3)次にconnection.Close()を実行します。
4)ここで接続= nullを

追加情報 を行い、私がテストするために使用しているサンプルです。

private void OnException(Exception ex) 
    { 
     XMSException xmsex = (XMSException)ex; 
     Console.WriteLine("Got exception"); 
     // Check the error code. 
     if (xmsex.ErrorCode == "XMSWMQ1107") 
     { 
      Console.WriteLine("This is a connection broken error"); 
      stopProcessing = true; // This is a class member variable 
     } 
    } 

接続が作成される方法で、例外リスナーを設定します。

 // Create connection. 
     connectionWMQ = cf.CreateConnection(); 
     connectionWMQ.ExceptionListener = new ExceptionListener(OnException); 

接続エラーが発生するたびに、例外リスナーが呼び出され、フラグがtrueに設定されます。

不要になったオブジェクトを処分することは良い習慣です。親子関係があり、Consumer、ProducerなどはConnectionの子であるSessionの子です。だから、処分の順序は、最初に子であり、次に親になることができます。しかし、親が処分されると、子供も自動的に処分されます。

+0

ありがとうシャーシ!私はあまり質問しないことを願っていますが、質問1に答えていることを示すサンプルコードはありますか? XMSWMQ1107のためのGoogleの検索は、この記事だけが現れます! – Sam

+0

プロデューサー、コンシューマー、セッション、リスナーを処分する必要がありますか?この記事を参照してください:http://stackoverflow.com/questions/12508473/ibm-mq-xms-subscription-not-closingこれを行う正しい順序は何ですか? – Sam

+0

私はExceptionListenerを実装しましたが、接続が切断されたときに検出されないため、IsConnectedフラグが設定されません。 – Sam

関連する問題