Frage

Ich habe 2 verschiedene Java -Projekte, einer hat 2 Klassen: dynamicbeans.DynamicBean2 und dynamic.Validator.

Zum anderen Projekt lade ich diese beiden Klassen dynamisch und speichere sie auf einem Object

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

Ich mache dann weiter und erstelle eine Validator Objekt verwendet validatorClass.newInstance() und lagern Sie es an validator Dann erstelle ich auch ein Bean -Objekt mit Verwendung beanClass.newInstance() und fügen Sie es der Sitzung hinzu.

portletRequest.setAttribute("DynamicBean2", bean);

Während des Lebenszyklus der Form Projekt, ich rufe an validator.validate() Das lädt das zuvor erstellte Bean -Objekt aus der Sitzung (ich leite WebSphere Portal Server aus). Wenn ich versuche, dieses Objekt wieder in a zu werfen DynamicBean2 Es scheitert mit einer ClassCastException.

Wenn ich das Objekt mithilfe der Sitzung wieder aus der Sitzung herausziehe

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

und überprüfen Sie die Klasse davon mithilfe .getClass() Ich bekomme dynamicbeans.DynamicBean2. Dies ist die Klasse, an die ich sie werfen möchte, aber wenn ich es versuche, bekomme ich die ClassCastException.

Irgendwelche Grund, warum ich das bekomme?

War es hilfreich?

Lösung

Ich folge nicht ganz Ihrer Beschreibung des Programmflusses, aber normalerweise, wenn Sie ClassCastExceptions erhalten, können Sie die Klasse mit einem Klassenloader geladen haben, dann versuchen Sie, sie in dieselbe Klasse zu geben, die von einem anderen Klassenloader geladen wird. Dies wird nicht funktionieren - sie werden durch zwei verschiedene Klassenobjekte im JVM dargestellt und die Besetzung wird fehlschlagen.

Da ist ein Artikel über Klassenbeladung in WebSphere. Ich kann nicht sagen, wie es für Ihre Anwendung gilt, aber es gibt eine Reihe möglicher Lösungen. Ich kann mir zumindest vorstellen:

  1. Ändern Sie den Kontextklassenlader manuell. Erfordert, dass Sie tatsächlich einen Verweis auf einen geeigneten Klassenlader erhalten können, der in Ihrem Fall möglicherweise nicht möglich ist.

    Thread.currentThread().setContextClassLoader(...);
    
  2. Stellen Sie sicher, dass die Klasse in der Hierarchie von einem Klassenlader höher geladen wird.

  3. Serialisieren und deserialisieren Sie das Objekt. (Yuck!)

Es gibt jedoch wahrscheinlich eine angemessenere Möglichkeit für Ihre spezielle Situation.

Andere Tipps

Die Klassenobjekte wurden in verschiedenen Klassenloadern geladen, daher werden die Instanzen, aus denen in jedem der Klassen erstellt wurde, als "inkompatibel" angesehen. Dies ist ein häufiges Problem in einer Umgebung, in der viele verschiedene Klassenlader verwendet werden und Objekte weitergegeben werden. Diese Probleme können leicht in Java EE und Portalumgebungen auftreten.

Wenn Sie eine Instanz einer Klasse gießen, muss die Klasse, die mit dem gegossenen Objekt verknüpft ist, der gleiche ist wie der, der vom aktuellen Thread Context Classloader geladen wird.

Ich habe das Problem der A2AcklassCastException erhalten, als ich versucht habe, eine Liste von Objekten aus XML mithilfe von Apache Commons Figester zu erstellen.

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
}

Wie oben erwähnt, ist die Ursache, dass der Fermenter nicht denselben Klassenloader wie der Rest des Programms verwendet. Ich habe das in Jboss geleitet, und es stellte sich heraus, dass Commons-Digester.jar nicht im LIB-Verzeichnis von Jboss, sondern im Lib-Verzeichnis eines Webapps war. Das Kopieren des JAR in MyWebapp/Web-inf/lib/lib löste ebenfalls das Problem. Eine andere Lösung bestand darin, Digrester.setClassloader (mytemplate.class.getClassloader ()), aber das fühlt sich in diesem Zusammenhang wie eine ziemlich hässliche Lösung an.

Ich hatte das gleiche Problem, als ich mehrere JBoss -Instanzen auf verschiedenen Maschinen verwendete. Zu schlecht bin ich nicht früher über diesen Beitrag gestolpert.
Auf verschiedenen Maschinen wurden Artefakte bereitgestellt, von denen zwei deklarierte Klassenlader mit identischem Namen.

Warum erwähnt die ClassCastException nicht die beteiligten Klassenlader? - Ich denke, das wären sehr nützliche Informationen.
Weiß jemand, ob es in Zukunft so etwas gibt? Es ist nicht angenehm, die Klassenlader von 20-30 Artefakten zu überprüfen. Oder gibt es etwas, das ich in dem Ausnahmetext verpasst habe?

BEARBEITEN: Ich habe die Meta-Inf/Jboss-App.xml-Datei bearbeitet und den Namen des Loaders geändert. Die Idee ist, einen eindeutigen Namen zu haben. Bei der Arbeit verwenden wir die Artefakt -ID (eindeutig) in Kombination mit der von Maven ({$ Version}) eingefügten Version während des Builds.
Die Verwendung dynamischer Felder ist nur optional, hilft jedoch, wenn Sie verschiedene Versionen derselben Anwendung bereitstellen möchten.

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

Hier finden Sie einige Informationen: https://community.jboss.org/wiki/classloadingConfiguration

Ich hatte das gleiche Problem und fand schließlich eine Problemumgehung auf Java.net:

Kopiere alles org.eclipse.persistence jar Dateien von glassfish4/glassfish/modules zu WEB-INF/lib. Dann geh in deine glassfish-web.xml, und set class-delegate zu false.

Arbeitete für mich!

Ich hatte ein ähnliches Problem mit Jaxb und JBoss wie 7,1. Das Problem und die Lösung werden hier beschrieben: javax.xml.bind.jaxBexception: Klasse *** noch eine seiner Superklassen ist diesem Kontext bekannt. Die Ausnahme, die gegeben wurde

Ich hatte das gleiche Problem auf einem Wildfly EJB, die EJB gab eine Liste von Objekten zurück und verfügt über eine Fernbedienung und eine lokale Schnittstelle. Ich habe die lokale Schnittstelle versehentlich verwendet, was gut funktioniert hat, bis Sie versuchen, die Objekte in die Liste zu geben.

Lokale/Remote -Schnittstelle:

public interface DocumentStoreService {

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

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

Die EJB -Bohne:

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

Die richtige Federverpackung um das 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>

Beachten Sie die $ remote, Sie können diese in $ local ändern und die lokale Schnittstelle findet in Ordnung und führt die Methoden ohne Probleme (aus einer separaten Anwendung auf demselben Container) aus, die Modellobjekte sind jedoch nicht marschal und sind nicht Aus einem anderen Klassenlader, wenn Sie versehentlich die lokale Schnittstelle verwenden.

Andere Option:

Ich war mir in Weblogic passiert, aber ich denke, es kann auch auf anderen Servern passieren - wenn Sie (nur) "veröffentlichen" und daher einige Ihrer Klassen erneut belastet werden. Machen Sie stattdessen "sauber", damit alle Klassen zusammengeladen werden.

Ich hatte das gleiche Problem mit einer EJB -Suche von einem anderen EJB. Ich habe addiert @remote (myInterface.class) zur EJB -Klassenkonfiguration gelöst

Hatte das gleiche my.package.MyClass cannot be cast to my.package.MyClass Auf Wildfly 10.1 und wie ich verstehe, habe ich das Gegenteil zu dem getan, was @emil Lundberg in seiner Antwort beschrieben hat.

Ich habe das hinzugefügt Modul (was beinhaltet my.package.MyClass) zu my.war/WEB-INF/jboss-deployment-structure.xml als Abhängigkeit

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

und die entsprechende Entfernung entfernt Krug aus my.war/WEB-INF/lib, neu gestaltete den Krieg neu und dann funktionierte der Code wie erwartet.

Daher haben wir sichergestellt, dass es das Problem löst. Jetzt müssen wir sicherstellen, dass das Problem nicht zurückkommt, beispielsweise wenn die aktualisierte Version von KRIEG wird zusammengestellt und eingesetzt.

Dafür in den Quellen dieser KRIEG, Es ist erforderlich, hinzuzufügen <scope>provided</scope> für diejenigen Krug in pom.xml, so, dass wann my.war wird das nächste Mal mit dem injizierten Fix/Enhancement-Code neu zusammengesetzt, er wird dies nicht bündeln Krug hinein my.war/WEB-INF/lib.

Ich bekam dieses Problem, nachdem ich eine Abhängigkeit hinzugefügt hatte spring-boot-devtools in meinem Springboot -Projekt. Ich habe die Abhängigkeit entfernt und das Problem verschwand. Meine beste Vermutung an diesem Punkt ist das spring-boot-devtools bringt einen neuen Klassenloader ein und verursacht in bestimmten Fällen, in denen der neue Klassenloader nicht von einigen Threads verwendet wird, das Problem von Klassengastproblemen zwischen verschiedenen Klassenloadern.

Bezug: Eine Dozer -Karte -Ausnahme im Zusammenhang mit Spring Boot Devtools

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top