2012-10-18 19 views
8

1.) किसी .net क्लाइंट से, मैं क्लाइंट से कनेक्ट होने पर (यानी भेज और प्राप्त कर सकता हूं) का परीक्षण कैसे करूं, हां, मैं कोशिश ब्लॉक के अंदर एक संदेश भेज सकता है और आने वाले अपवाद को पकड़ सकता है लेकिन मैं एक और अधिक सुरुचिपूर्ण समाधान की उम्मीद कर रहा हूं।मैं वेबस्पेयर एमक्यू कनेक्शन की स्थिति कैसे प्राप्त करूं और मैं कनेक्शन को रीसेट कैसे करूं:

2) मैं कनेक्शन कैसे खोलूं, बंद कर सकता हूं और फिर से खोल सकता हूं? ऊपर प्रश्न 1 को हल करने के मेरे प्रयासों में मैंने पाया कि यदि मैं कनेक्शन खोलता हूं तो कनेक्शन कॉल करें। बंद करें() मैं कनेक्शन फैक्ट्री से एक और कनेक्शन प्राप्त करने में सक्षम नहीं हूं (नीचे कोड खंड देखें)। मुझे त्रुटि संदेश प्राप्त होता है XMSCC0008

मैं एक बहुत ही मानक वेनिला एमक्यू कॉन्फ़िगरेशन का उपयोग कर रहा हूं। यहां बताया गया है कि मेरा क्लाइंट कैसे कनेक्ट करता है:

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 एक छोटी उपयोगिता कक्षा है।

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)); 
        } 
       } 
      } 
     } 
    } 
} 

संपादित करें: MQClient का नाम बदलकर MQAccess वर्ग। इसे टी टी रॉब सुझाव प्रति उदाहरण कक्षा बना दिया। डिस्कनेक्ट पद्धति अभी भी ऊपर

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

समस्या सूचीबद्ध त्रुटि msgs साथ दुर्घटनाओं यहाँ है ->where MQAccess is a small utility class.

प्रश्न के पहले भाग पूछता है कि कनेक्शन सक्रिय है बताने के लिए कैसे। वेबस्पेयर एमक्यू के लिए एक्सएमएस कक्षाएं गैर-जावा प्लेटफ़ॉर्म के लिए जेएमएस विनिर्देश का कार्यान्वयन हैं। वे जेएमएस स्पेक का काफी बारीकी से पालन करते हैं और जेएमएस स्पेक के पास isConnected के समतुल्य कनेक्शन या सत्र पर कोई विधि नहीं है इसलिए न तो एक्सएमएस करता है। हालांकि, JMS अपवादों को पकड़ने के लिए सभी GET और PUT गतिविधि को प्रयास/पकड़ ब्लॉक के भीतर होना चाहिए। (जिसमें से आप हमेशाlinkedException प्रिंट करते हैं, है ना?) जब एक जेएमएस अपवाद फेंक दिया जाता है तो ऐप या तो इसे घातक के रूप में मानता है और मर जाता है या अन्यथा यह कनेक्शन फैक्ट्री को छोड़कर सभी जेएमएस ऑब्जेक्ट्स को बंद करता है, कुछ सेकंड इंतजार करता है और फिर पुनः- कनेक्शन अनुक्रम ड्राइव करता है।

अद्यतन सवाल में नई जानकारी के आधार पर:
MQAccess वर्ग पोस्टिंग के लिए धन्यवाद। यह क्या हो रहा है में काफी अंतर्दृष्टि प्रदान करता है, हालांकि अभी भी कोई कोड नहीं दिखा रहा है कि कनेक्शन बंद है और प्रश्न के भाग # 2 के अनुसार फिर से खोला गया है।

हालांकि, कोड है कि MQAccess वर्ग ICONNECTION connection के एक निजी उदाहरण के रूप में वर्ग उदाहरण का निर्माण किया है, जो तब MQAccess.GetConnection के रूप में सार्वजनिक रूप से सामने आ रहा है बनाता है पता चलता है। वर्तमान में पोस्ट किए गए MQAccess वर्ग में कोई सार्वजनिक या निजी क्लास विधि नहीं है जो connection द्वारा आयोजित कनेक्शन हैंडल को प्रतिस्थापित करेगी, इसलिए MQAccess.Connection.Close() को कभी भी कहा जाता है, IConnection ऑब्जेक्ट उदाहरण MQAccess कक्षा के भीतर एक अवैध कनेक्शन हैंडल रखने के बाद हमेशा के लिए होगा। एक बार कनेक्शन बंद होने के बाद, MQAccess का उदाहरण प्रभावी रूप से मृत हो गया है। नया कनेक्शन प्राप्त करने के लिए आपको MQAccess को हटाना और पुनर्स्थापित करना होगा।

MQAccess वर्ग कनेक्शन कारखाना सार्वजनिक रूप से बेनकाब तो सिद्धांत रूप में यह वर्ग बाहर से MQAccess.GetConnection फोन और एक मान्य नई IConnection वस्तु प्राप्त, मूल एक बंद करने के बाद भी संभव हो जाएगा करता है।हालांकि, यह उदाहरण MQAccess वर्ग के दायरे से बाहर मौजूद होगा और इस प्रकार MQAccess पर आने वाली किसी भी कॉल को कक्षा के बाहर बनाए गए नए कनेक्शन उदाहरण के बजाय इसके निष्क्रिय उदाहरण चर connection का संदर्भ दिया जाएगा।

यदि आपको कनेक्शन बंद करने और फिर से बनाने की आवश्यकता है, तो आप इसे MQAccess के अंदर से प्रबंधित करने पर विचार कर सकते हैं। एक कम तकनीक दृष्टिकोण कनेक्शन के लिए MQAccess.Close() विधि लिखना हो सकता है जो मौजूदा कनेक्शन को बंद कर देगा, तुरंत पर कॉल करें ताकि निजी connection चर हमेशा वैध कनेक्शन हैंडल रख सके।

यदि यह समस्या का समाधान नहीं करता है, तो कृपया कनेक्शन को बंद करने और पुनर्निर्माण करने वाले कोड को पोस्ट करें।

वैसे, नेटवर्क कनेक्शन पर गैर-लेनदेन सत्र WMQ समेत किसी भी जेएमएस प्रदाता के लिए संदेशों को खोने या डुप्लिकेट करने की संभावना को खोलता है। क्या आप इसका इरादा रखते थे? मैंने समझाया है कि यह एक अन्य एसओ पोस्ट here में क्यों है।

+0

धन्यवाद टी रॉब यह वास्तव में सहायक है।आप सही हैं - कक्षा को नियंत्रक में एमक्यू शुरू नहीं करना चाहिए। LinkException से आपका क्या मतलब है? – Sam

+0

जेएमएस अपवाद (और इसलिए जेएमएस मॉडल के बाद से एक्सएमएस अपवाद) एक बहु-स्तरीय संरचना है। जेएमएस में शीर्ष स्तर में "कनेक्ट करने में विफल" जैसे सामान्य अपवाद होते हैं लेकिन बाद के स्तर में प्रदाता-विशिष्ट डेटा होता है जैसे "QMgr नहीं मिला" या "गलत QMgr नाम"। यदि एक लिंक किया गया अपवाद मौजूद है, तो शायद इसमें ऐसी जानकारी है जो डायग्नोस्टिक्स के साथ मदद करेगी। कृपया ['LinkedException'] देखें (http://pic.dhe.ibm.com/infocenter/wmqv7/v7r5/topic/com.ibm.mq.msc.doc/sapiexcpt.html#sapiexcpt_getlkex) –

+0

ओह कभी नहीं सोचा वह जुड़ाव अपवाद IllegalStateException की एक संपत्ति है। – Sam

5

टी.रोब से टिप्पणियों में जोड़ना।

प्रश्न 1:
मुझे आशा है कि आपके पास MQAccess के स्रोत कोड तक पहुंच होगी। यदि हां, तो आप MQAccess में एक संपत्ति का पर्दाफाश कर सकते हैं जो इंगित करता है कि कोई कनेक्शन सक्रिय है या नहीं। यदि आपके पास पहुंच नहीं है तो आपको इस संपत्ति को जोड़ने के लिए उस वर्ग के लेखक से पूछना पड़ सकता है। आप संपत्ति को सेट/रीसेट करने के लिए निम्न कार्य कर सकते हैं।

1) के बाद संपत्ति सेट करें कनेक्शन कनेक्शन विधि सफलतापूर्वक लौटती है।
2) कनेक्शन के लिए अपवाद श्रोता सेट करें।
3) अपवाद हैंडलर में संपत्ति को रीसेट करें। कारण कोड जांचें और संपत्ति को रीसेट करें यदि यह कनेक्शन टूटी हुई त्रुटि है (XMSWMQ1107 और लिंक किए गए अपवाद में एमक्यूआरसी 200 हो सकता है)।

प्रश्न 2
यदि आप हमें दिखा सकते हैं कि आप closing और reopening कनेक्शन कैसे हैं, तो यह आपकी सहायता करेगा। कनेक्शन बंद करने की मेरी सिफारिश है:
1) पहले कनेक्शन करें। रोकें()।
2) किसी भी संदेश श्रोताओं को हटाएं, मूल रूप से उपभोक्ता करें। मैसेज लिस्टनर = शून्य।
3) फिर कनेक्शन करें। बंद करें()।
4) एक कनेक्शन = अशक्त

अतिरिक्त सूचना यहाँ नमूना मैं परीक्षण करने के लिए इस्तेमाल किया है है मत करो।

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); 

जब भी कोई कनेक्शन त्रुटि हो, अपवाद श्रोता को बुलाया जाएगा और ध्वज सत्य पर सेट हो जाएगा।

ऑब्जेक्ट्स को निपटाने के लिए यह एक अच्छा अभ्यास है जब उन्हें अब आवश्यकता नहीं है। माता-पिता के बच्चे संबंध हैं, उपभोक्ता, निर्माता आदि सत्र के बच्चे हैं जो बदले में कनेक्शन का बच्चा है। तो निपटान का आदेश पहले बच्चे और माता-पिता हो सकता है। लेकिन अगर माता-पिता का निपटारा किया जाता है, तो बच्चों को स्वचालित रूप से निपटाया जाता है।

+0

धन्यवाद शशी! मुझे आशा है कि मैं बहुत ज्यादा नहीं पूछूंगा, लेकिन क्या आपके पास कोई उदाहरण कोड है जो आपको प्रश्न 1 का जवाब देता है? XMSWMQ1107 के लिए एक Google खोज केवल इस पोस्ट को बदल देती है! – Sam

+0

क्या निर्माता, उपभोक्ता, सत्र और श्रोताओं का निपटान करना आवश्यक है? यह पोस्ट देखें: http://stackoverflow.com/questions/12508473/ibm-mq-xms- सदस्यता- नोट- बंद करना ऐसा करने का सही क्रम क्या है? – Sam

+0

मैंने एक अपवाद लिस्टर को कार्यान्वित किया हालांकि कनेक्शन का टूटने पर यह पता नहीं लगाया गया है और इसलिए मेरा कनेक्टेड ध्वज सेट नहीं होता है। – Sam

संबंधित मुद्दे