2012-11-26 19 views
8

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

public interface WordManagerMXBean { 
    public void addWord(String word); 
    public WordsObject getWords(); 
    public void removeWord(String word); 
} 

WordsObject एक कस्टम, serializable सर्वर की स्थिति के बारे डेटा पुनः प्राप्त करने के लिए इस्तेमाल वर्ग है। तब मेरे पास वर्डमैनेजर क्लास भी है जो उपरोक्त इंटरफ़ेस को लागू करता है। मैं तो मेरे संसाधन प्रबंधन के लिए एक JMX एजेंट बनाने के लिए:

MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); 
ObjectName wordManagerName = new ObjectName("com.example:type=WordManager"); 
mbs.registerMBean(wordManager, wordManagerName); 

मैं एक ग्राहक है कि इन तरीकों का आह्वान बनाया है, और यह उम्मीद के रूप में काम करता है। हालांकि, मैं उपयोगकर्ता परिभाषित अपवाद जोड़कर इस मौजूदा कॉन्फ़िगरेशन को विस्तारित करना चाहता हूं जिसे मेरे क्लाइंट को वापस भेजा जा सकता है। इसलिए मैं कुछ इस तरह करने के लिए अपने इंटरफेस को बदलना चाहते हैं:

public interface WordManagerMXBean { 
    public void addWord(String word) throws WordAlreadyExistsException; 
    public WordsObject getWords(); 
    public void removeWord(String word); 
} 

मेरे WordAlreadyExistsException इस तरह दिखता है:

public class WordAlreadyExistsException extends Exception implements Serializable { 

private static final long serialVersionUID = -9095552123119275304L; 

public WordAlreadyExistsException() { 
    super(); 
    } 
} 

जब मैं अपने ग्राहक में addWord() विधि कहते हैं, मैं प्राप्त करना चाहते हैं यदि शब्द पहले से मौजूद है तो WordAlreadyExistsException वापस करें। हालांकि, जब मैं यह कर, मैं एक त्रुटि इस तरह मिलती है:

java.rmi.UnmarshalException: Error unmarshaling return; nested exception is: 
java.lang.ClassNotFoundException: com.example.WordAlreadyExistsException 

WordAlreadyExistsException, WordsObject और WordManagerMXBean इंटरफ़ेस एक भी जार फ़ाइल कि दोनों क्लाइंट और सर्वर के लिए उपलब्ध है में सभी कर रहे हैं। अगर मैं getWords() विधि को कॉल करता हूं, तो क्लाइंट को WordObject को संभालने में कोई कठिनाई नहीं होती है। हालांकि, यदि कोई उपयोगकर्ता अपवाद परिभाषित करता है, जैसा ऊपर दिया गया है, तो फेंक दिया जाता है, तो क्लाइंट ऊपर दिखाए गए त्रुटि देता है। क्लाइंट में इस अपवाद को सही तरीके से संभालने के लिए जेएमएक्स को कॉन्फ़िगर करना संभव है?

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

मैंने दोनों चेक और अनचेक अपवादों के साथ भी कोशिश की है, फिर भी वही त्रुटि होती है।

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

क्या जेएमएक्स में उपयोगकर्ता परिभाषित अपवादों को संभालना संभव है? यदि हां, तो कोई विचार कैसे?

संपादित करें: पूर्ण स्टैक ट्रेस

java.lang.reflect.UndeclaredThrowableException 
at $Proxy4.addWord(Unknown Source) 
at com.example.TestClient.addWord(TestClient.java:76) 
at com.example.TestClient.execute(TestClient.java:56) 
at java.lang.Thread.run(Thread.java:722 
Caused by: java.rmi.UnmarshalException: Error unmarshaling return; nested exception is: 
java.lang.ClassNotFoundException: com.example.WordAlreadyExistsException 
at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:245) 
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:160) 
at com.sun.jmx.remote.internal.PRef.invoke(Unknown Source) 
at javax.management.remote.rmi.RMIConnectionImpl_Stub.invoke(Unknown Source) 
at javax.management.remote.rmi.RMIConnector$RemoteMBeanServerConnection.invoke(RMIConnector.java:1017) 
at javax.management.MBeanServerInvocationHandler.invoke(MBeanServerInvocationHandler.java:305) 
... 6 more 
Caused by: java.lang.ClassNotFoundException: com.example.WordAlreadyExistsException 
at java.net.URLClassLoader$1.run(URLClassLoader.java:366) 
at java.net.URLClassLoader$1.run(URLClassLoader.java:355) 
at java.security.AccessController.doPrivileged(Native Method) 
at java.net.URLClassLoader.findClass(URLClassLoader.java:354) 
at java.lang.ClassLoader.loadClass(ClassLoader.java:423) 
at java.lang.ClassLoader.loadClass(ClassLoader.java:356) 
at java.lang.Class.forName0(Native Method) 
at java.lang.Class.forName(Class.java:264) 
at sun.rmi.server.LoaderHandler.loadClass(LoaderHandler.java:453) 
at sun.rmi.server.LoaderHandler.loadClass(LoaderHandler.java:184) 
at java.rmi.server.RMIClassLoader$2.loadClass(RMIClassLoader.java:637) 
at java.rmi.server.RMIClassLoader.loadClass(RMIClassLoader.java:264) 
at sun.rmi.server.MarshalInputStream.resolveClass(MarshalInputStream.java:216) 
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1593) 
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1514) 
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1750) 
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1347) 
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1964) 
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1888) 
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1771) 
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1347) 
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:369) 
at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:243) 
... 11 more 
+3

_sure_ उस वर्ग ग्राहक classloader में मौजूद है आप कर रहे हैं? आप एक पुराने जार या कुछ और के साथ नहीं चल रहे हैं ? – jtahlborn

+1

हां, मुझे यकीन है। मैंने अपने शब्द ऑब्जेक्ट क्लास को एक अतिरिक्त फ़ील्ड, जार पुनर्निर्माण, और मौजूदा जार फ़ाइल को नए के साथ बदलने के लिए संशोधित करके इसकी पुष्टि की। जब मैंने क्लाइंट को फिर से चलाया, तो मुझे नया फ़ील्ड मिल सकता था WordsObject में, लेकिन मैं अभी भी वें मिलता है अपवाद के साथ एक ही त्रुटि। – Daniel

+2

क्या आपने यह पुष्टि करने के लिए जार की सामग्री का निरीक्षण किया है कि वर्ग वहां है और सही पैकेज में है? – jtahlborn

उत्तर

4

मैंने समस्या को पुन: उत्पन्न करने की कोशिश की, हालांकि यह मेरे लिए ठीक काम करता है ;-(नीचे अपवाद आउटपुट देखें। मैं यह भी शर्त लगाऊंगा कि यह वास्तव में क्लाइंट पक्ष पर एक क्लास लोडिंग मुद्दा है। क्या यह संभव है कि आप पोस्ट कर सकता अपने ग्राहक जार के (एक नीचे छीन) संस्करण (और शायद के रूप में अच्छी स्रोत)?

Exception in thread "main" javax.management.MBeanException: WordAlreadyExistsException 
at com.sun.jmx.mbeanserver.MBeanIntrospector.unwrapInvocationTargetException(MBeanIntrospector.java:283) 
at com.sun.jmx.mbeanserver.MBeanIntrospector.invokeM(MBeanIntrospector.java:210) 
..... 
Caused by: WordAlreadyExistsException 
at WordManager.addWord(WordManager.java:7) 
..... 
+2

पर कॉपी नहीं किया गया है, तो क्लाइंट पक्ष पर क्लास लोडिंग समस्या होने के बारे में आपकी धारणा सही है। मेरे क्लाइंट के लिए, मैं क्लैमशेल-क्ली फ्रेमवर्क का उपयोग कर रहा था, जो सर्विसलोडर एपीआई के आधार पर प्लगइन आर्किटेक्चर का उपयोग करता है। मेरी जार फ़ाइल क्लैमशेल के लिए एक प्लगइन है। तो हालांकि मेरी जार फ़ाइल में अपवाद है, यह वर्ग लोड नहीं लग रहा है। मैंने फिर जार फ़ाइल को क्लैम्सहेल में एक lib निर्देशिका में भी जोड़ा। ऐसा करने के बाद, कक्षा को सही ढंग से लोड किया गया प्रतीत होता है, और अपवाद को वांछित के रूप में फेंक दिया जाता है। – Daniel

+0

यह अजीब लगता है कि मेरे शब्द ऑब्जेक्ट को उसी पैकेज में सही तरीके से लोड किया जा रहा था, लेकिन अब किसी भी मामले में समस्या हल हो गई है। आपकी सहायता के लिए धन्यवाद. – Daniel

0

आपका अपवाद मामले में से

javax.management.JMException 

या

javax.management.JMRuntimeException 

का विस्तार किया जाना चाहिए यह एक RuntimeException है भी शामिल है।

+1

मैंने एमबीएएनएक्सप्शन और रनटाइम एमबीएशन अपवाद दोनों को विस्तारित करने का प्रयास किया है। ये javax.management.JMException और javax.management.JMRuntimeException का विस्तार करें। जब मैं ऐसा करता हूं तो वही त्रुटि होती है। क्या आपको कुछ सफलता मिली है? – Daniel

+0

जब मेरे पास कक्षाएं हों तो मुझे अपवाद नहीं मिला। मुझे दृढ़ता से संदेह है कि इसके क्लासस्पैट या आपके जार में कक्षा नहीं है। –

+0

@ user1802492 मेरा उत्तर यह स्पष्ट करने के लिए है कि जेएमएक्स कार्यान्वयन JMException या JMRuntimeException को फेंकना होगा। यह या तो विस्तार या लपेटकर हो सकता है। –

0

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

विस्तार RuntimeMBeanException भी जार फ़ाइल प्रदान काम कर सकते हैं वर्ग पथ में मौजूद है, लेकिन मैं परीक्षण नहीं किया था कि

+0

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

+0

मैंने jConsole के साथ इसका परीक्षण किया है। मैंने जार फ़ाइल को \ jre \ lib \ ext फ़ोल्डर में कॉपी किया और यह काम किया। यह java.rmi.UnmarshalException फेंक देगा यदि जार फ़ाइल को \ jre \ lib \ ext फ़ोल्डर – user1802492

1

क्या हो रहा जा सकता है कि अपने कस्टम अपवाद धारावाहिक है और फिर वापस आवेदन सर्वर के भीतर deserialized है, लेकिन एक बेहतर शब्द, "क्लासलोडर नेमस्पेस" की कमी के लिए अलग-अलग में।

ऐपसेवर का उपयोग कर रहे आपके जेएमएक्स जार के साथ कस्टम अपवाद कक्षाओं को एक साथ जार (सी) रखने का प्रयास करें। आप पुराने स्थान से पुराने जार अवश्य निकाल दें (मैं इसे की वेब-INF/lib में यह निश्चित रूप से संभव है, हालांकि अनुशंसित नहीं, कस्टम अपवाद फेंक संभालने हूँ कहीं

1

JMX Best practices से:।।

यह अनुशंसा की जाती है कि एमबीएन्स द्वारा फेंकने वाले अपवादों को जावा में परिभाषित मानक सेट से निकाला जाए। * और जावैक्स। * जावा एसई प्लेटफ़ॉर्म पर पैकेज। यदि कोई एमबीन गैर-मानक अपवाद फेंकता है, तो में कोई क्लाइंट नहीं है उस अपवाद वर्ग की संभावना जैसे क्लास नॉटफाउंडएक्सप्शन के बजाय एक और अपवाद दिखाई देगी।

इसलिए, मैं कुछ पैसे डालूंगा जो आपके क्लाइंट ने WordAlreadyExistsException कक्षा को लोड नहीं किया था। आप इसे अपेक्षाकृत सरल देख सकते हैं - क्लाइंट क्लाइंट में एक विधि लिखें जो इस अपवाद को फेंकता है, इसे आमंत्रित करें और देखें कि क्या होता है। अगर सब कुछ ठीक हो गया (ठीक = कस्टम अपवाद फेंक दिया गया था, ClassNotFoundException) तो सुनिश्चित करें कि आपके क्लाइंट और सर्वर में जार का एक ही संस्करण है जिसमें WordAlreadyExistsException है। यहां तक ​​कि मामूली विसंगति (उदाहरण के लिए, पैकेज नाम में) आपकी समस्या का स्रोत हो सकती है।