2012-05-30 13 views
6

के साथ धूमकेतु सत्र जोड़ना हमारे पास जेट्टी 8.1, डोजो और धूमकेतु का उपयोग करके एक वेब एप्लिकेशन है जो सिंक्रोनस ऑपरेशंस के लिए एक JSON/HTTP REST API (2) का उपयोग कर ब्राउज़र और वेब कंटेनर के बीच इंटरैक्ट करता है और (2) एक धूमकेतु API सर्वर से कई घटनाओं को प्राप्त करने के लिए।HTTP सत्र

हम पूरी तरह से स्पष्ट नहीं हैं कि इन दो अलग-अलग एपीआई के प्रमाणीकरण सत्रों का सुंदर प्रबंधन कैसे करें, खासकर जब से हमारे लिए धूमकेतु नियमित रूप से HTTP के बजाय वेबसाईट का उपयोग करेगा। एप्लिकेशन मानक जेटी एलडीएपी मॉड्यूल का उपयोग कर फॉर्म-आधारित प्रमाणीकरण का उपयोग कर रहा है। तो एक HTTP नजरिए से कंटेनर जो इस तरह दिखता है एक मानक jsessionid साथ ब्राउज़र प्रदान करता है:

Cookie: jsessionid=758E2FAD7C199D722DA8B5E243E0E27D 

सिमोन Bordet पद here यह अनुशंसा की जाती समाधान cometd हाथ मिलाना के दौरान इस टोकन पारित करने के लिए है लगता है के आधार पर किया जाता है जो कि हम क्या कर रहे हैं।

हमारे पास समस्या यह है कि दो मूलभूत रूप से अलग सत्र हैं - HTTP सत्र और Bayeux धूमकेतु सत्र। संभावित मेमोरी लीक और सुरक्षा मुद्दों जैसे कारणों से, हम चाहते हैं कि वे एकजुट हो जाएं या "जोड़े गए" हों। यदि किसी उपयोगकर्ता का HTTP सत्र समाप्त हो जाता है, तो हम संबंधित Bayeux सत्र को समाप्त करने के साथ-साथ इसके विपरीत भी चाहते हैं। क्या ऐसा करने का एक अनुशंसित तरीका है?

उत्तर

11

HTTP सत्र और CometD सत्र अलग lifecycles है: उदाहरण के लिए, अगर वहाँ एक अस्थायी कनेक्शन विफलता है, CometD सत्र असफल हो जायेगी, और सर्वर फिर से हाथ मिलाना करने के लिए ग्राहक के लिए पूछना होगा, इस प्रकार एक अलग CometD बनाने सत्र (एक ही उपयोगकर्ता का प्रतिनिधित्व करता है, लेकिन एक अलग धूमकेतु clientId के साथ)। उसी स्थिति में, HttpSession वही रहेगा।

इसे ध्यान में रखते हुए, आपको एप्लिकेशन स्तर पर - उपयोगकर्ता नाम के बीच मैपिंग, संवाददाता HttpSession, और संवाददाता ServerSession को बनाए रखने की आवश्यकता है। चलिए इस मैपिंग को HttpCometDMapper पर कॉल करें। हर बार एक नया उपयोगकर्ता में लॉग करता है, आप इसका नाम (या उपयोगकर्ता का एक और अद्वितीय पहचानकर्ता), HttpSession रजिस्टर, और वर्तमान ServerSession। शायद आप एक द्विस्तरीय प्रक्रिया है, जहां आप पहले उपयोगकर्ता नाम और HttpSession, और फिर ServerSession साथ ही उपयोगकर्ता नाम लिंक की आवश्यकता होगी।

तो एक CometD फिर से हाथ मिलाना किया जाता है, तो आप नए ServerSession साथ नक्शाकार अद्यतन करें।

आप इतनी है कि जब इसे नष्ट कर दिया है, तो आप नक्शाकार से वर्तमान CometD ServerSession निकालते हैं और उस पर ServerSession.disconnect() फोन HttpSession के लिए एक HttpSessionListener पंजीकरण से दो सत्रों लिंक कर सकते हैं।

वाइसवर्सा थोड़ा सा ट्रिकियर है क्योंकि धूमकेतु में HttpSession जैसे निष्क्रियता टाइमआउट की अवधारणा नहीं है। इसे अपने तर्क के साथ आवेदन में लागू किया जाना चाहिए।

एक कर का हिस्सा है, ServerSession पर एक RemoveListener रजिस्टर करने के लिए है कि तरह है:

serverSession.addListener(new ServerSession.RemoveListener() 
{ 
    public void removed(ServerSession session, boolean timeout); 
    { 
     if (!timeout) 
     { 
      // Explicitly disconnected, invalidate the HttpSession 
      httpCometDMapper.invalidate(session); 
     } 
    } 
}); 

यह श्रोता ग्राहक से स्पष्ट डिस्कनेक्ट (और सर्वर - reentrancy से सावधान) के लिए देखता है।

थोड़ा अधिक कठिन गैर स्पष्ट डिस्कनेक्ट के लिए एक ही तंत्र को लागू करने के लिए है।इस मामले में, timeout पैरामीटर सत्य होगा, लेकिन अस्थायी नेटवर्क विफलता (क्लाइंट के विपरीत गायब होने के विपरीत) के कारण हो सकता था, और उसी उपयोगकर्ता ने पहले से ही ServerSession के साथ फिर से हाथ से पकड़ लिया होगा।

मुझे लगता है कि इस मामले में एक एप्लिकेशन टाइमआउट समस्या हल कर सकता है: जब आप ServerSession को टाइमआउट के कारण हटा देते हैं, तो आप उस उपयोगकर्ता को नोट करते हैं और एप्लिकेशन टाइमआउट शुरू करते हैं। यदि एक ही उपयोगकर्ता फिर से हैंडशेक, एप्लिकेशन टाइमआउट रद्द करें; अन्यथा उपयोगकर्ता वास्तव में चला गया है, एप्लिकेशन टाइमआउट समाप्त हो जाता है, और आप HttpSession को भी अमान्य कर देते हैं।

ऊपर क्या विचार और सुझाव हैं; वास्तविक कार्यान्वयन आवेदन विवरण पर भारी निर्भर करता है (और यही कारण है कि धूमकेतु द्वारा बॉक्स के बाहर प्रदान नहीं किया जाता है)।

प्रमुख बिंदु नक्शा हैं, HttpSessionListener और RemoveListener, और उन घटकों के जीवन चक्र को जानना। एक बार जब आप इसे प्रबंधित कर लेंगे, तो आप सही कोड लिख सकते हैं जो आपके आवेदन के लिए सही चीज करता है।

अंत में, ध्यान दें कि धूमकेतु HttpSession के साथ BayeuxContext उदाहरण के माध्यम से बातचीत करने का एक परिवहन-अज्ञेय तरीका है, जिसे आप BayeuxServer.getContext() से प्राप्त कर सकते हैं। मेरा सुझाव है कि आप यह भी देखें कि यह चीजों को सरल बना सकता है, खासकर HttpSession में संग्रहीत टोकन को पुनर्प्राप्त करने के लिए।

0

क्या कोई समस्या आई है यदि हम अस्थायी कनेक्शन विफलता के बाद BayeuxClient बनाने जा रहे हैं?

आप नीचे दिए गए कोड के साथ प्रयास कर सकते हैं।

try { 
     log.info("Running streaming client example...."); 
     makeConnect(); 


    } catch (Exception e) { 
     handleException("Error while setup the salesforce connection.", e); 
    } 
} 



private void makeConnect() { 
    try{ 
     client = makeClient(); 
     client.getChannel(Channel.META_HANDSHAKE).addListener 
       (new ClientSessionChannel.MessageListener() { 
        public void onMessage(ClientSessionChannel channel, Message message) { 
         log.info("[CHANNEL:META_HANDSHAKE]: " + message); 
         boolean success = message.isSuccessful(); 
         if (!success) { 
          String error = (String) message.get("error"); 
          if (error != null) { 
           log.error("Error during HANDSHAKE: " + error); 
          } 

          Exception exception = (Exception) message.get("exception"); 
          if (exception != null) { 
           handleException("Exception during HANDSHAKE: ", exception); 
          } 
         } 
        } 
       }); 

     client.getChannel(Channel.META_CONNECT).addListener(
       new ClientSessionChannel.MessageListener() { 
        public void onMessage(ClientSessionChannel channel, Message message) { 
         log.info("[CHANNEL:META_CONNECT]: " + message); 
         boolean success = message.isSuccessful(); 

         if (!success) { 
          client.disconnect(); 
          makeConnect(); 
          String error = (String) message.get("error"); 
          if (error != null) { 
           //log.error("Error during CONNECT: " + error); 
          } 
         } 
        } 

       }); 

     client.getChannel(Channel.META_SUBSCRIBE).addListener(
       new ClientSessionChannel.MessageListener() { 
        public void onMessage(ClientSessionChannel channel, Message message) { 
         log.info("[CHANNEL:META_SUBSCRIBE]: " + message); 
         boolean success = message.isSuccessful(); 
         if (!success) { 
          String error = (String) message.get("error"); 
          if (error != null) { 
           makeConnect(); 
           log.error("Error during SUBSCRIBE: " + error); 
          } 
         } 
        } 
       }); 
     client.handshake(); 
     log.info("Waiting for handshake"); 
     boolean handshaken = client.waitFor(waitTime, BayeuxClient.State.CONNECTED); 
     if (!handshaken) { 
      log.error("Failed to handshake: " + client); 
     } 
     log.info("Subscribing for channel: " + channel); 
     client.getChannel(channel).subscribe(new MessageListener() { 
      public void onMessage(ClientSessionChannel channel, Message message) { 
       injectSalesforceMessage(message); 
      } 
     }); 
     log.info("Waiting for streamed data from your organization ..."); 
    }catch (Exception e) { 
     handleException("Error while setup the salesforce connection.", e); 
    } 

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