2013-11-14 9 views
9

में नहीं पकड़े जाने मेरी Grails सेवा में मैं निम्नलिखित की तरह कोड है:अपवाद सेवा से फेंका नियंत्रक

def createCharge(chargeParams) { 
    try { 
    def charge = Charge.create(chargeParams) 
    } catch (CardException e) { 
    throw e 
    } 
} 

मेरी नियंत्रक से मैं निम्नलिखित है:

try { 
    service.createCharge(chargeParams) 
} catch(CardException e) { 

} 

लेकिन, मेरा नियंत्रक है कार्ड अपवाद की पुनः फेंकने को पकड़ नहीं। अगर मैं के माध्यम से एक RuntimeException में CardException लपेट:

throw new RuntimeException(e) 

और/या हस्ताक्षर बस पकड़ने के लिए (ई) यह लिखे बिना पकड़ से हटा दें, यह काम करता है, लेकिन मैं संदेश की तरह, अपवाद से कुछ जानकारी खोना ।

एक नोट के रूप में, कार्ड अपवाद एक अपवाद है, न कि रनटाइम अपवाद। मुझे यकीन नहीं है कि यह मायने रखता है।

उत्तर

11

जावा के विपरीत, आपको ग्रोवी विधि द्वारा फेंकने वाले (चेक किए गए) अपवादों की घोषणा करने की आवश्यकता नहीं है, क्योंकि किसी भी अविकसित चेक अपवाद UndeclaredThrowableException में लिपटे हैं। तो यह:

def createCharge(chargeParams) { 
    try { 
    def charge = Charge.create(chargeParams) 
    } catch (CardException e) { 
    throw e 
    } 
} 

प्रभावी रूप से एक ही है के रूप में:

def createCharge(chargeParams) throws UndeclaredThrowableException { 
    try { 
    def charge = Charge.create(chargeParams) 
    } catch (CardException e) { 
    throw new UndeclaredThrowableException(e) 
    } 
} 

अपवाद ऊपर द्वारा फेंका, जाहिर द्वारा पकड़ा नहीं होगी:

try { 
    service.createCharge(chargeParams) 
} catch(CardException e) { 

} 

लेकिन यह पकड़ा हो जाएगा द्वारा:

try { 
    service.createCharge(chargeParams) 
} catch(e) { 

} 

क्योंकि यह बस के लिए एक आशुलिपि है:

try { 
    service.createCharge(chargeParams) 
} catch(Exception e) { 

} 
+0

ठीक है, मुझे अपने मामले में अपवादों की जांच की आवश्यकता है क्योंकि कई ऐसे हैं जिन्हें मुझे स्ट्रिप एपीआई से निपटने की ज़रूरत है। मैं एक अलग मार्ग पर जा रहा था क्योंकि मुझे हमेशा एक रनटाइम अपवाद फेंकने की ज़रूरत है ताकि मेरे लेनदेन सही ढंग से रोलबैक हो जाएं। मैं आपके उत्तर को सही के रूप में चिह्नित कर रहा हूं क्योंकि यह मेरे प्रश्न का सही जवाब है। धन्यवाद। – Gregg

+2

आपका स्वागत है। बीटीडब्लू, आप अपने Grails सेवाओं के लिए निम्नलिखित एनोटेशन जोड़कर सभी अपवादों (चेक और अनचेक) के लिए लेन-देन रोलबैक कर सकते हैं '@ ट्रान्सएक्शनल (रोलबैकफॉर = थ्रोबल)' –

+0

टिप के लिए धन्यवाद! वह नहीं जानता था। – Gregg

8

जावा के विपरीत, आप, (चयनित) अपवाद है कि एक ग्रूवी विधि से फेंक दिया जाता है की घोषणा करने के क्योंकि किसी भी अघोषित जांचे हुए अपवादों एक UndeclaredThrowableException में लिपटे रहे हैं नहीं है।

आप सूचित करते हैं कि ग्रूवी wraps एक UndeclaredThrowableException द्वारा अपवाद जाँच लगते हैं, यह स्थिति नहीं है। यदि एक Grails सेवा एक अनचेक अपवाद फेंकता है अपवाद अंततः एक UndeclaredThrowableException द्वारा लपेटा जाता है लेकिन यह एक java.lang.reflection तंत्र है और केवल तब होता है जब प्रॉक्सी कक्षा शामिल होती है।

ऐसा होता है क्योंकि एक Grails सेवा शामिल है। मुझे यकीन नहीं है कि कितने प्रॉक्सी कक्षाएं वास्तव में कम से कम एक हैं: एक वर्ग जो लेनदेन हैंडलिंग (वसंत द्वारा) करता है।

कक्षा एक लेन-देन के साथ सेवा में किसी भी विधि को लपेटेगी और एक रनटाइम अपवाद होने पर लेनदेन को रोलबैक करेगा। डिफ़ॉल्ट रूप से वसंत लेनदेन प्रबंधन चेक अपवाद के मामले में रोलबैक नहीं करता है।

जावा

यह सादे पुराने जावा में समझ में आता है, के बाद से डेवलपर आवेदन कोड में अपवाद देखेंगे और इसके बारे में कुछ करने के लिए चेतावनी दी जाएगी। यदि डेवलपर स्मार्ट है तो वह लेनदेन के दायरे के दौरान किसी भी अपवाद से निपटेंगे।यदि वह लेनदेन को वापस नहीं लेता है तो वह मूल रूप से कह रहा है: "इस स्थिति में, लेनदेन द्वारा प्रदान की गई डेटा अखंडता मेरे लिए महत्वपूर्ण नहीं है। मैं किसी और तरीके से "

ग्रूवी

यह एक ग्रूवी दुनिया में कोई मतलब नहीं है क्योंकि ग्रूवी संकलक अपवाद के साथ काम कर लागू नहीं करता है में इस त्रुटि को ठीक होगा। यह प्रभाव में अपवादों को ठीक उसी तरह से व्यवहार करता है जैसे RuntimeExceptions।

हालांकि एक चेतावनी है: प्रतिबिंब तंत्र प्रॉक्सी द्वारा निकाला गया अपवाद देखता है जो मूल सेवा के विधि हस्ताक्षर में नहीं है। यह संभव है क्योंकि:

  1. ग्रूवी अपवाद
  2. एक प्रॉक्सी विधि हमेशा किसी भी फेंकने योग्य (जाँच InvocationHandler JavaDoc)

क्योंकि प्रतिबिंब इस्तेमाल किया तंत्र जावा से है फेंक कर सकते हैं निपटने लागू नहीं करता है, यह जावा नियमों के अनुरूप होना चाहिए। तो इसे अपवाद को एक रनटाइम अपवाद में लपेटना होगा, .. इस मामले में एक UndeclaredThrowableException।

Grails

अब यह वास्तव में मुश्किल है क्योंकि अगर आप एक नियंत्रक से अपने सेवा विधि कॉल और एक अपवाद तब होता हो जाता है। आप एक रनटाइम अपवाद बबल अप देखेंगे (कुछ छुपे हुए तंत्र की वजह से) लेकिन आपका लेनदेन वापस लुढ़का नहीं जाएगा (कुछ छुपे हुए तंत्र की वजह से)।

यह व्यवहार बहुत ही खतरनाक है के रूप में डेवलपर वास्तव में ठीक से किसी भी अपवाद (जो संकलक के साथ मदद नहीं करेगा) से निपटने के लिए याद करने के लिए है या डेवलपर सुनिश्चित करें कि किसी भी सेवा ठीक से @Transactional साथ निर्देश दिया जाता है बनाने के लिए है (रोलबैक के लिए = थ्रोबल)।

यह एक डिज़ाइन मुद्दा है जो मुझे लगता है कि ग्रिल के डेवलपर्स ने इसे पहली बार डिज़ाइन किया है। लेकिन मुझे लगता है कि डिफ़ॉल्ट व्यवहार इतना गलत है और इतना खतरनाक है कि इसे वास्तव में बदला जाना चाहिए।

2

मुझे लगता है कि समस्या का सरल समाधान सेवा पद्धति में throws CardException कथन जोड़ना है, इस प्रकार अपवाद अब UndeclaredTrowableException में लपेटा नहीं जाएगा और नियंत्रक उचित अपवाद प्रकार को पकड़ लेगा।

0

बस UndeclaredThrowableException को पकड़ें, इससे संदेश प्राप्त करें, और फिर आवश्यकता होने पर फिर से फेंक दें।

catch (UndeclaredThrowableException e) { 
    def s = e.getUndeclaredThrowable().getMessage() 
    // do something with the message 
    throw e 
} 

ऊपर कोड टुकड़ा सिर्फ अपवाद आप स्पष्ट रूप से कोड (जैसे CardException) में फेंक दिया गया है पकड़ लेंगे। उदाहरण के लिए एक NullPointerException पकड़ा नहीं जाएगा और बुलबुला नहीं होगा।

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