2009-05-05 11 views
39

मेरे पास 2 अलग-अलग जावा प्रोजेक्ट हैं, एक में 2 कक्षाएं हैं: dynamicbeans.DynamicBean2 और dynamic.Validatorक्लासकास्ट अपवाद उसी श्रेणी में कास्टिंग करते समय

अन्य परियोजना पर, मैं इन कक्षाओं में गतिशील रूप से दोनों लोड और एक Object

class Form { 
    Class beanClass; 
    Class validatorClass; 
    Validator validator; 
} 
एक सेम

मैं तो आगे जाना है और validatorClass.newInstance() का उपयोग कर एक Validator वस्तु बना सकते हैं और validator पर संग्रहीत तो मैं बनाने पर उन्हें स्टोर ऑब्जेक्ट के साथ-साथ beanClass.newInstance() का उपयोग करके और सत्र में जोड़ें।

portletRequest.setAttribute("DynamicBean2", bean); 

Form परियोजना के जीवन चक्र के दौरान, मैं validator.validate() जो सत्र (मैं Websphere पोर्टल सर्वर चल रहा हूँ) से पहले बनाया था सेम वस्तु को लोड करता है कहते हैं। जब मैं इस ऑब्जेक्ट को DynamicBean2 में डालने का प्रयास करता हूं तो यह क्लासकास्ट अपवाद के साथ विफल रहता है।

जब मैं

faces.getApplication().createValueBinding("#{DynamicBean2}").getValue(faces); 

का उपयोग कर सत्र से बाहर वापस वस्तु खींच और .getClass() का उपयोग कर रहा dynamicbeans.DynamicBean2 प्राप्त यह वर्ग की जाँच करें। यह वह वर्ग है जिसे मैं इसे डालना चाहता हूं, हालांकि जब मैं कोशिश करता हूं कि मुझे क्लासकास्ट अपवाद प्राप्त होता है।

मुझे यह कारण क्यों मिल रहा है?

उत्तर

47

मैं प्रोग्राम प्रवाह के आपके विवरण का काफी पालन नहीं कर रहा हूं, लेकिन आमतौर पर जब आप क्लासकास्ट एक्सेप्शन प्राप्त करते हैं तो आप यह नहीं समझा सकते कि आपने कक्षा को एक क्लासलोडर के साथ लोड किया है, फिर इसे किसी अन्य क्लासलोडर द्वारा लोड की गई कक्षा में डालने का प्रयास करें। यह काम नहीं करेगा - वे जेवीएम के अंदर दो अलग-अलग वर्ग वस्तुओं द्वारा प्रतिनिधित्व किए जाते हैं और कलाकार विफल हो जाएंगे।

एक article about classloading in WebSphere है। मैं नहीं कह सकता कि यह आपके आवेदन पर कैसे लागू होता है, लेकिन कई संभावित समाधान हैं। मैं कम से कम सोच सकता हूं:

  1. संदर्भ वर्ग लोडर मैन्युअल रूप से बदलें। यह आवश्यक है कि आप वास्तव में उपयुक्त वर्ग लोडर का संदर्भ प्राप्त कर सकें, जो आपके मामले में संभव नहीं हो सकता है।

    Thread.currentThread().setContextClassloader(...); 
    
  2. सुनिश्चित करें कि वर्ग पदानुक्रम में उच्च श्रेणी के लोडर द्वारा लोड किया गया है।

  3. ऑब्जेक्ट को क्रमबद्ध और deserialize। (यक!)

हालांकि आपकी विशेष स्थिति के लिए शायद एक और उचित तरीका है।

+3

मेरा अनुमान लगाया है (मुझे पोर्टल सर्वर के साथ अनुभव नहीं है) यह है कि आप विभिन्न पोर्टलों में कक्षा लोड कर रहे हैं, प्रत्येक को अपने स्वयं के क्लासलोडर के साथ। फिर आप इंस्टेंस को सत्र ऑब्जेक्ट में रखें, और जब आप इसे गलत पोर्टलेट से पुनर्प्राप्त करते हैं (जिसमें से इसे बनाया गया था) तो आपका अपवाद है। मुझे लगता है कि होगा (था अनुभव के आधार पर) है कि आप classloading पदानुक्रम में कहीं अधिक अपनी कक्षा के साथ जार जगह इतना है कि यह दोनों portlets classloaders की एक माता पिता के द्वारा लोड किया जाता है की जरूरत है। विवरण के साथ – Robin

+2

यानी संख्या 2। – Robin

+1

@waxwing यह काफी समय रहा है। लेकिन, क्या आप पहले संभावित समाधान को विस्तारित करने के बारे में सोचेंगे? मुझे लगता है कि मेरे द्वारा एक मुद्दा हल किया जा सकता है। अग्रिम में धन्यवाद! –

10

कक्षा वस्तुओं को विभिन्न क्लासलोडरों में लोड किया गया था, इसलिए प्रत्येक वर्ग में से बनाए गए उदाहरण 'असंगत' के रूप में देखे जाते हैं। यह एक ऐसे माहौल में एक आम मुद्दा है जहां कई अलग-अलग क्लासलोडर्स का उपयोग किया जा रहा है और वस्तुओं को पारित किया जा रहा है। जावा ईई और पोर्टल वातावरण में ये समस्याएं आसानी से उत्पन्न हो सकती हैं।

किसी वर्ग के उदाहरण को कास्ट करने की आवश्यकता है कि ऑब्जेक्ट से जुड़ी कक्षा से जुड़ी कक्षा वर्तमान थ्रेड संदर्भ क्लासलोडर द्वारा लोड की गई है।

+0

वहाँ एक सही तरीके से मैं वर्गों ऐसा होने से रोकने के लिए लोड करना चाहिए है? –

+0

रहस्यमय हिस्सा क्यों दो वर्ग लोडर एक ही कक्षा लोड करना चाहिए है। किसी भी जावा एप्लिकेशन में किसी वर्ग को हमेशा एक वर्ग लोडर द्वारा लोड किया जाना चाहिए। जब भी आपको यह व्यवहार मिलता है तो वास्तव में अजीब आपके वर्ग लोडर के साथ चल रहा है। –

+2

यह उस वातावरण पर निर्भर करता है जिसमें आप काम कर रहे हैं। यदि आप जानकारी को कैश करने के लिए सिंगलटन का उपयोग करते हैं, और आप उसी कैश में डेटा को उसी ईएआर में दो अलग-अलग वेबैप से डालते हैं, तो उनमें से प्रत्येक का अपना क्लासलोडर उदाहरण बना सकता है, और जब किसी अन्य आइटम को अन्य कैश से इस कैश से पुनर्प्राप्त किया जाता है, इसके परिणामस्वरूप क्लासकास्ट अपवाद होगा। इन वातावरणों में मेमोरी डेटा में साझा करना बहुत मुश्किल हो सकता है, इसलिए आपको इस बात से अवगत होना चाहिए कि काम करने के लिए कक्षाएं कहां से लोड की जा रही हैं। – Robin

0

अपाचे कॉमन्स डायजेस्टर का उपयोग करके एक्सएमएल से वस्तुओं की सूची बनाने की कोशिश करते समय मुझे A2AClassCastException समस्या मिली।

List<MyTemplate> templates = new ArrayList<MyTemplate>(); 
Digester digester = new Digester(); 
digester.addObjectCreate("/path/to/template", MyTemplate.class); 
digester.addSetNext("/path/to/template", "add"); 
// Set more rules... 
digester.parse(f); // f is a pre-defined File 

for(MyTemplate t : templates) { // ClassCastException: Cannot cast mypackage.MyTemplate to mypackage.MyTemplate 
    // Do stuff 
} 

जैसा ऊपर बताया गया है, इसका कारण यह है कि डायजेस्टर प्रोग्राम के बाकी हिस्सों के समान क्लासलोडर का उपयोग नहीं करता है। मैंने इसे जेबॉस में चलाया, और यह पता चला कि कॉमन्स-digester.jar जेबॉस की lib निर्देशिका में नहीं था, बल्कि एक वेबएप की lib निर्देशिका में था। जार को mywebapp/WEB-INF/lib में कॉपी करने से समस्या हल हो गई। एक और समाधान casll digester.setClassLoader (MyTemplate.class.getClassLoader()) था, लेकिन यह इस संदर्भ में काफी बदसूरत समाधान की तरह लगता है।

0

विभिन्न मशीनों पर कई जेबॉस उदाहरणों का उपयोग करते समय मुझे एक ही समस्या थी। बुरा होने के लिए मैंने पहले इस पोस्ट में ठोकर खाई नहीं।
विभिन्न मशीनों पर तैनात कलाकृतियों को रखा गया था, उनमें से दो ने समान नाम वाले क्लास लोडर घोषित किए थे। मैंने क्लासलोडर नामों में से एक को बदल दिया और सब ठीक काम किया => & कॉपी से सावधान रहें!

क्लासकास्ट अपवाद को शामिल वर्ग लोडर्स का उल्लेख क्यों नहीं किया जाता है? - मुझे लगता है कि यह बहुत उपयोगी जानकारी होगी।
क्या किसी को पता है कि भविष्य में ऐसा कुछ भी होगा? 20-30 कलाकृतियों के वर्ग लोडर की जांच करने की आवश्यकता सुखद नहीं है। या क्या अपवाद पाठ में कुछ याद आया है?

EDIT: मैंने मेटा-आईएनएफ/jboss-app.xml फ़ाइल संपादित की और लोडर का नाम बदल दिया, विचार एक अद्वितीय नाम है। काम पर हम निर्माण के दौरान मैवेन ({$ संस्करण}) द्वारा डाले गए संस्करण के साथ आर्टिफैक्ट आईडी (अद्वितीय) का उपयोग करते हैं।
गतिशील फ़ील्ड का उपयोग केवल वैकल्पिक है लेकिन यदि आप उसी एप्लिकेशन के विभिन्न संस्करणों को तैनात करना चाहते हैं तो सहायता करता है।

<jboss-app> 
    <loader-repository> 
    com.example:archive=unique-archive-name-{$version} 
    </loader-repository> 
</jboss-app> 

आप यहाँ कुछ जानकारी पा सकते हैं: https://community.jboss.org/wiki/ClassLoadingConfiguration

+0

क्या आप दिखा सकते हैं कि आपने यह कैसे किया है, कुछ कोड? – Rachel

+0

मैंने अपना जवाब अपडेट किया, देर से होने के लिए खेद है। – Andrei

0

मैं एक ही मुद्दा था, और मैं अंत में java.net पर एक समाधान पाया:

कॉपी सभी org.eclipse.persistence jarglassfish4/glassfish/modules से WEB-INF/lib करने के लिए फ़ाइलों। फिर अपने glassfish-web.xml पर जाएं, और class-delegate से false पर सेट करें।

मेरे लिए काम किया!

0

मुझे जेएक्सबी और जेबॉस एएस 7.1 के साथ एक समान समस्या थी। समस्या और समाधान यहां वर्णित हैं: javax.xml.bind.JAXBException: Class *** nor any of its super class is known to this context। दिया गया अपवाद org.foo.bar.ValueSet को org.foo.bar पर नहीं डाला जा सकता है। वैल्यूसेट

0

मेरे पास जंगली उड़ान ईजेबी पर एक ही समस्या थी, ईजेबी ऑब्जेक्ट्स की एक सूची लौटा रहा था और रिमोट है और एक स्थानीय इंटरफ़ेस। मैंने स्थानीय इंटरफ़ेस का उपयोग गलती से किया था जो उस समय तक ठीक काम कर रहा था जब तक आप सूची में ऑब्जेक्ट्स को डालने का प्रयास नहीं करते थे।

स्थानीय/रिमोट इंटरफ़ेस:

public interface DocumentStoreService { 

    @javax.ejb.Remote 
    interface Remote extends DocumentStoreService { 
    } 

    @javax.ejb.Local 
    interface Local extends DocumentStoreService { 
    } 

EJB सेम:

@Stateless 
public class DocumentStoreServiceImpl implements DocumentStoreService.Local, DocumentStoreService.Remote { 

EJB के आसपास सही वसंत आवरण:

<bean id="documentStoreService" class="org.springframework.ejb.access.LocalStatelessSessionProxyFactoryBean"> 
    <property name="jndiName" value="java:global/dpc/dpc-ejb/DocumentStoreServiceImpl!santam.apps.dpc.service.DocumentStoreService$Remote"/> 
    <property name="businessInterface" value="santam.apps.dpc.service.DocumentStoreService$Remote"/> 
    <property name="resourceRef" value="true" /> 
</bean> 

नोट $ रिमोट, आप बदल सकते हैं यह $ स्थानीय में है और यह स्थानीय इंटरफ़ेस को ठीक ठीक लगेगा, और बिना किसी समस्या के विधियों को निष्पादित करेगा (जैसा से एक ही कंटेनर पर eparate आवेदन), लेकिन मॉडल वस्तुओं मार्शल और अगर आप गलती से स्थानीय इंटरफ़ेस का उपयोग एक अलग वर्ग लोडर से कर रहे हैं नहीं कर रहे हैं।

0

एक अन्य विकल्प:

weblogic में मेरे साथ हुआ है, लेकिन मुझे लगता है कि यह रूप में अच्छी तरह अन्य सर्वर में हो सकता है - अगर आप करते हैं (बस) "प्रकाशित करें" और वजह अपनी कक्षाओं में से कुछ को फिर से लोड किए गए हैं। इसके बजाय "साफ करें" ताकि सभी वर्ग एक साथ फिर से लोड हो जाएंगे।

1

मैं एक EJB से एक EJB देखने के साथ एक ही समस्या थी। मैंने ईजेबी क्लास कॉन्फ़िगरेशन

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