2009-10-17 9 views
11

मुझे कई साथी डेवलपर्स से बार-बार "सुझाव" मिल रहा है। मेरे अनुभव में मैंने पाया है कि ईजेबीएक्सप्शन बीन इंस्टेंस परिप्रेक्ष्य से "दुनिया के अंत" के लिए उपयुक्त हैं (जैसे कि कुछ गलत है कि बीन इंस्टेंस स्वयं ठीक नहीं हो सकता है)। यदि कोई उदाहरण ठीक हो सकता है, तो मुझे लगता है कि एप्लिकेशन अपवाद फेंकना बेहतर है।क्यों एक ईजेबीएक्सप्शन फेंकना एक "अनुशंसित" अभ्यास है?

 
private SomeResource resource; 
ejbCreate: 
    resource = allocateResource(...); 

omMessage: 
    try { 
    ... 
    } catch (JMSException e) { 
     throw new EJBException(e); 
    } 

ejbRemove: 
    freeResource(resource); 

IMHO यह एक antipattern कि संसाधन लीक का कारण बनता है:

यहाँ पैटर्न है कि मैं बार बार मिलते हैं।

संपादित: विशेष रूप से, EJB विनिर्देश का कहना है कि अगर एक सेम व्यापार विधि से एक क्रम अपवाद फेंकता है (और EJBException एक क्रम अपवाद नहीं है), तो सेम उस पर ejbRemove बुला बिना त्याग दिया जाता है।

क्या यह एक ईजेबीएक्सप्शन फेंकने के खिलाफ एक प्रासंगिक उदाहरण है? ईजेबीएक्सप्शन फेंकने पर प्रासंगिक मामले क्या हैं?

+0

@vinny_g: मैंने अपने (अब हटाए गए) "उत्तर" पर आपकी टिप्पणी से स्पष्टीकरण जोड़ा है। –

उत्तर

7

EJBException की फेंकने मामलों में जहां EJB एक अपवाद यह मुठभेड़ों से वापस नहीं ले पाता में (EJB 3 में 14.2.2) EJB कल्पना द्वारा सिफारिश की है। स्पेक यह भी कहता है कि ईजेबी कंटेनर को प्रसारित करने के लिए सिस्टम अपवादों को उचित रूप से (अनचेक) अनुमति दे सकता है।

मैं इस spec के अपने पढ़ने के साथ सहमत हूं कि इस तरह के मामलों में जीवन चक्र चक्र कॉलिंग विधियों को कंटेनर द्वारा नहीं बुलाया जाएगा, और इसलिए आपकी चिंता है कि ejbRemove() कॉलबैक में सामान्य रूप से होने वाली कोई संसाधन-व्यवस्था नहीं होगी और इसलिए संसाधन रिसाव का खतरा है।

मेरा अनुभव यह है कि रक्षात्मक कोडिंग की कमी के कारण बहुत सी मुश्किल समस्याएं उत्पन्न होती हैं। "स्थिति एक्स एक अच्छी तरह से व्यवहार प्रणाली में नहीं हो सकता है, और यदि यह करता है तो पूरी प्रणाली टूट जाती है, इसलिए मैं उस घटना के लिए कोड नहीं दूंगा।" फिर हमें सितारों और ऑपरेटर त्रुटियों के कुछ "रोचक" संरेखण मिलते हैं और "उत्तराधिकारी" जल्दी उत्तराधिकार में कई बार होता है और अप्रत्याशित साइड इफेक्ट्स किक समस्याओं का निदान करने में वास्तव में कठिन होता है।

इसलिए मैं कहूंगा:

  1. एक राज्य में बीन उदाहरण छोड़ने के लिए जहां एक व्यापार विधि के अगले मंगलाचरण काम करने के लिए सक्षम हो सकता है सब कुछ आप कर सकते हैं मत करो। इसका मतलब हो सकता है अपवाद और बंद संसाधन जो त्रुटि में हैं। इस मामले में आप कॉलर्स को बताने के लिए चुन सकते हैं, "माफ करना guv, वह अनुरोध काम नहीं करता है, लेकिन हो सकता है कि आप बाद में पुनः प्रयास करें ..." मैं TransientException चेक अपवाद फेंक कर ऐसा करता हूं।
  2. यदि आपके पास ejbRemove में कोई महत्वपूर्ण हाउसकीपिंग नहीं है तो आप SystemExceptions को प्रचार करने की अनुमति दे सकते हैं - लेकिन मुझे यकीन नहीं है कि यह अनुकूल है। आप एक पुस्तकालय पर निर्भर करते हैं और यह NullPointerException फेंकता है। TransientException पकड़ने और पुनर्स्थापित करने के लिए वास्तव में अधिक मजबूत है?
  3. यदि आपके पास महत्वपूर्ण हाउसकीपिंग है, तो मुझे लगता है कि आपको सभी अपवादों को पकड़ने की आवश्यकता है और कम से कम सफाई का प्रयास करें। फिर आप EJBException या सिस्टम अपवाद को फिर से बदलना चुन सकते हैं ताकि इंस्टेंस नष्ट हो जाए, लेकिन कम से कम आपने हाउसकीपिंग करने की कोशिश की है।
0

लीक संसाधन चाहे या नहीं, यह संसाधन इस बात पर निर्भर करता है कि उन संसाधनों को कैसे प्रशासित किया जाता है। छोड़ा गया बीन एकत्रित कचरा हो जाता है जो संसाधन के संदर्भ को छोड़ देता है जो बदले में कचरा इकट्ठा हो जाता है जब कोई संदर्भ संदर्भित नहीं होता है। यदि संसाधन को रूट के पथ के साथ संग्रह में भी रखा जाता है, तो यह तब तक रिसाव हो जाएगा जब तक कंटेनर में पूल मैनेजर न हो जो निष्क्रिय संसाधनों का पता लगा सके और इसे रीसायकल कर सके।

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

2

कंटेनर अभी भी वर्तमान लेनदेन कर सकता है भले ही ईजेबी विधि ने एप्लिकेशन अपवाद फेंक दिया हो। अपने EJB विधि एक आवेदन अपवाद फेंक कर सकते हैं तो आप इस तरह EJBContext.setRollbackOnly() का उपयोग पर विचार करना चाहिए:

public void method() throws ApplicationException { 
    try { 
    ... 
    } catch (ApplicationException e) { 
     _context.setRollbackOnly(); 
     throw e; 
    } 
} 

एक EJBException या एक प्रणाली (अनियंत्रित) अपवाद मतलब यह है कि कंटेनर स्वचालित रूप से लेन-देन रोलबैक होगा फेंकने। देखें: http://java.sun.com/j2ee/tutorial/1_3-fcs/doc/Transaction3.html

यदि आपके सिस्टम के ईजेबी नियमित रूप से जाल और आवेदन अपवादों को संभाल नहीं पाते हैं तो कोड जो उन्हें फेंकता है, उसके परिणामस्वरूप आंशिक रूप से पूर्ण ऑपरेशन हो सकता है।

इससे हार्ड-टू-बग की समस्या हो सकती है क्योंकि सीएमपी के साथ एक ईजेबी विधि का "उपयोगकर्ता मिथक" यह है कि यह एक लेनदेन के लिए मानचित्र है, जो परमाणु है। आंशिक रूप से पूर्ण व्यावसायिक तर्क डेटाबेस पर परमाणु रूप से प्रतिबद्ध है। जब यह अभ्यास में होता है तो यह बेहद भ्रमित होता है। लीक अबास्ट्रक्शन पर जोएल का लेख: http://www.joelonsoftware.com/articles/LeakyAbstractions.html बताता है क्यों।

यदि आपके सिस्टम में ईजेबी हैं जो एप्लिकेशन अपवादों को सही तरीके से संभाल नहीं पाते हैं तो तार्किक उत्तर उन्हें ठीक करना है ताकि वे ऐसा कर सकें। जब तक समस्या ठीक नहीं हो जाती है, तब तक आपकी टीम के पास तर्कसंगत कारण हो सकता है कि ईजेबी से आवेदन अपवादों को नहीं फेंक दिया जाए।

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