سؤال

لدي مشروعان مختلفان في Java، أحدهما يحتوي على فئتين: dynamicbeans.DynamicBean2 و dynamic.Validator.

في المشروع الآخر، قمت بتحميل كلا الفئتين ديناميكيًا وقمت بتخزينهما في ملف Object

class Form {
    Class beanClass;
    Class validatorClass;
    Validator validator;
}

ثم أمضي قدمًا وأقوم بإنشاء ملف Validator الكائن باستخدام validatorClass.newInstance() وتخزينها على validator ثم أقوم بإنشاء كائن فول باستخدامه أيضًا beanClass.newInstance() وإضافته إلى الجلسة.

portletRequest.setAttribute("DynamicBean2", bean);

خلال دورة حياة Form المشروع، أدعو validator.validate() الذي يقوم بتحميل كائن الفول الذي تم إنشاؤه مسبقًا من الجلسة (أنا أقوم بتشغيل Websphere Portal Server).عندما أحاول إعادة هذا الكائن إلى ملف DynamicBean2 فشل مع ClassCastException.

عندما أقوم بسحب الكائن مرة أخرى خارج الجلسة باستخدام

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

وتحقق من فئة استخدامه .getClass() انا حصلت dynamicbeans.DynamicBean2.هذا هو الفصل الذي أرغب في إرساله إليه ولكن عندما أحاول الحصول على ClassCastException.

هل هناك أي سبب وراء حصولي على هذا؟

هل كانت مفيدة؟

المحلول

أنا لا أتابع وصفك لتدفق البرنامج تمامًا، ولكن عادةً عندما تحصل على ClassCastExceptions، لا يمكنك توضيح أنك قمت بتحميل الفصل باستخدام أداة تحميل فئة واحدة ثم حاول إرساله إلى نفس الفئة التي تم تحميلها بواسطة أداة تحميل فئة أخرى.لن ينجح هذا - حيث يتم تمثيلهما بواسطة كائنين مختلفين من فئة داخل JVM وسيفشل الإرسال.

هناك مقالة عن تحميل الفصول الدراسية في WebSphere.لا أستطيع أن أقول كيف ينطبق ذلك على طلبك، ولكن هناك عدد من الحلول الممكنة.أستطيع أن أفكر على الأقل في:

  1. قم بتغيير مُحمل فئة السياق يدويًا.يتطلب أن تتمكن فعليًا من الحصول على مرجع لمحمل فئة مناسب، وهو ما قد لا يكون ممكنًا في حالتك.

    Thread.currentThread().setContextClassLoader(...);
    
  2. تأكد من تحميل الفصل بواسطة مُحمل فئة أعلى في التسلسل الهرمي.

  3. إجراء تسلسل وإلغاء تسلسل الكائن.(ياك!)

ربما تكون هناك طريقة أكثر ملاءمة لموقفك الخاص.

نصائح أخرى

تم تحميل كائنات فئة في classloaders مختلفة، وبالتالي فإن الحالات التي تم إنشاؤها من ينظر إليها في كل الفصول باسم 'يتعارض'. هذه هي قضية مشتركة في بيئة حيث هناك العديد من classloaders مختلفة تستخدم ويتم تمرير الأشياء المحيطة. ويمكن لهذه القضايا تنشأ بسهولة في جاوة EE والبيئات بوابة.

وصب مثيل فئة يتطلب أن فئة مرتبطة الكائن الذي يتم محمل هي نفس واحدة تحميلها بواسطة الحالي classloader سياق الموضوع.

وحصلت مشكلة A2AClassCastException عند محاولة إنشاء قائمة الكائنات من XML باستخدام أباتشي العموم الهاضم.

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
}

وكما ذكر أعلاه، والسبب هو أن هاضم لا يستخدم نفس ClassLoader مثل بقية البرنامج. ركضت هذا في جبوس، واتضح أن المشاعات-digester.jar لم يكن في الدليل ليب جبوس، وانما في دليل ليب لتطبيق الويب ل. نسخ جرة في mywebapp / WEB-INF / ليب تحل أيضا مشكلة. وكان الحل آخر لcasll digester.setClassLoader (MyTemplate.class.getClassLoader ())، ولكن هذا يبدو وكأنه تماما حل القبيح في هذا السياق.

واجهت نفس المشكلة أثناء استخدام العديد من مثيلات JBoss على أجهزة مختلفة.من المؤسف أنني لم أتعثر على هذا المنشور في وقت سابق.
كانت هناك عناصر منشورة على أجهزة مختلفة، اثنان منها أعلنا عن محمل فئة باسم متطابق. لقد قمت بتغيير أحد أسماء محمل الفصل وكل شيء يعمل بشكل جيد => احذر من النسخ واللصق!

لماذا لا يذكر ClassCastException مُحمِّلات الفئة المعنية؟- أعتقد أن هذه ستكون معلومات مفيدة للغاية.
هل يعرف أحد ما إذا كان سيكون هناك شيء مثل هذا متاحًا في المستقبل؟إن الحاجة إلى التحقق من أدوات تحميل الفصل التي تحتوي على 20-30 قطعة أثرية ليست أمرًا ممتعًا.أم أن هناك شيئًا فاتني في نص الاستثناء؟

يحرر:لقد قمت بتحرير ملف META-INF/jboss-app.xml وغيرت اسم المُحمل، والفكرة هي أن يكون له اسم فريد.في العمل نستخدم معرف القطعة الأثرية (الفريد) مع الإصدار المدرج بواسطة maven({$version}) أثناء الإنشاء.
يعد استخدام الحقول الديناميكية أمرًا اختياريًا فقط ولكنه يساعد إذا كنت تريد نشر إصدارات مختلفة من نفس التطبيق.

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

يمكنك العثور على بعض المعلومات هنا: https://community.jboss.org/wiki/ClassLoadingConfiguration

وكان لي نفس المشكلة، وأخيرا وجدت الحل على java.net:

ونسخ جميع الملفات org.eclipse.persistence jar من glassfish4/glassfish/modules إلى WEB-INF/lib. ثم انتقل في glassfish-web.xml، وتعيين class-delegate إلى false.

وعملت بالنسبة لي!

وكان لي مشكلة مشابهة مع JAXB وجبوس AS 7.1. ووصف القضية والحل هنا: <لأ href = "https://stackoverflow.com/questions/14057932/javax-xml-bind-jaxbexception-class-nor-any-of-its-super-class-is-known ومن المعروف الدرجة *** ولا أي من فئتها عظمى في هذا السياق : -to-ر / 41526616 # 41526616 "> javax.xml.bind.JAXBException. الاستثناء الذي أعطيت كان org.foo.bar.ValueSet لا يمكن أن يلقي لorg.foo.bar.ValueSet

وكان لي نفس المشكلة على EJB wildfly، وEJB كان عائدا قائمة الأجسام ويحتوي على جهاز التحكم عن بعد واجهة المحلية. لقد استخدمت واجهة المحلية عن طريق الخطأ ما كان يعمل فقط غرامة تصل إلى النقطة التي محاولة تحويل الكائنات في القائمة.

ومحلية / عن بعد واجهة:

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>

ملحوظة عن بعد $، يمكنك تغيير هذا إلى $ المحلية، وسوف تجد واجهة المحلية على ما يرام، وأيضا تنفيذ الطرق دون أي قضية (من تطبيق منفصل على نفس الحاوية)، ولكن الكائنات نموذج لا تنظيم وهي من محمل فئة مختلفة إذا كنت تستخدم الواجهة المحلية عن طريق الخطأ.

وثمة خيار آخر:

وحدث لي في يبلوغيتش، ولكن أعتقد أنه يمكن أن يحدث في خوادم أخرى أيضا - إذا كنت تفعل (فقط) "نشر" و لذلك بعض الفصول الدراسية وإعادة تحميلها. بدلا من ذلك القيام به "نظيفة" لذلك كل الطبقات وإعادة تحميلها معا.

وكان لي نفس المشكلة مع بحث EJB من EJB آخر. I حلها مضيفاRemote (MyInterface.class) لتكوين الطبقة EJB

كان نفس الشيء my.package.MyClass cannot be cast to my.package.MyClass على WildFly 10.1، وكما أفهم، فعلت عكس ما وصفهEmil Lundberg في إجابته.

لقد أضفت وحدة (الذي يحتوي my.package.MyClass) ل my.war/WEB-INF/jboss-deployment-structure.xml باعتبارها التبعية

<dependencies>
    ...
    <module name="my.package"/>
</dependencies>

وإزالة المقابلة إناء من my.war/WEB-INF/lib, ، وأعد نشر WAR ثم عمل الكود كما هو متوقع.

وهكذا تأكدنا من أنه يحل المشكلة.الآن، نحتاج إلى التأكد من أن المشكلة لن تعود مرة أخرى، على سبيل المثال، عند تحديث الإصدار حرب سيتم تجميعها ونشرها.

لهذا، في مصادر تلك حرب, ، يشترط الإضافة <scope>provided</scope> لأولئك إناء في pom.xml, ، بحيث عندما my.war يتم إعادة تجميعه في المرة القادمة مع إدخال رمز الإصلاح/التحسين، فلن يتم تجميع هذا إناء داخل my.war/WEB-INF/lib.

وكنت الحصول على هذه المشكلة بعد إضافة تبعية إلى spring-boot-devtools في مشروع Springboot بلدي. I إزالة التبعية وذهب بعيدا المشكلة. أفضل تخمين لي في هذه النقطة هو أن spring-boot-devtools يجلب في classloader الجديد والذي يسبب المشكلة من مشاكل الطبقة الصب بين classloaders مختلفة في بعض الحالات التي لا يتم استخدام classloader جديد من قبل بعض المواضيع.

والمرجعي: خريطة بلدوزر استثناء المتعلقة الربيع devtools التمهيد

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top