Domanda

Ho 2 diversi progetti Java, uno ha 2 classi: dynamicbeans.DynamicBean2 e dynamic.Validator.

Nell'altro progetto, carico entrambe queste classi in modo dinamico e le memorizzo su un Object

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

Vado avanti e creo un Validator oggetto usando validatorClass.newInstance() e lo memorizzo su validator quindi creo un oggetto bean anche usando beanClass.newInstance() e lo aggiungo alla sessione.

portletRequest.setAttribute("DynamicBean2", bean);

Durante il ciclo di vita del progetto Form, chiamo validator.validate() che carica l'oggetto bean precedentemente creato dalla sessione (sto eseguendo Websphere Portal Server). Quando provo a riportare questo oggetto in DynamicBean2 fallisce con ClassCastException.

Quando estraggo l'oggetto dalla sessione usando

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

e controlla la sua classe usando .getClass() Ottengo <=>. Questa è la classe in cui voglio lanciarla, tuttavia quando provo ottengo ClassCastException.

Qualche motivo per cui sto ricevendo questo?

È stato utile?

Soluzione

Non sto seguendo esattamente la tua descrizione del flusso del programma, ma di solito quando ottieni ClassCastExceptions non puoi spiegare che hai caricato la classe con un classloader, quindi prova a lanciarla sulla stessa classe caricata da un altro classloader. Questo non funzionerà: sono rappresentati da due diversi oggetti Class all'interno della JVM e il cast fallirà.

C'è un articolo sul classloading in WebSphere . Non posso dire come si applica alla tua applicazione, ma ci sono una serie di possibili soluzioni. Mi viene in mente almeno:

  1. Modifica manualmente il caricatore di classi di contesto. Richiede che tu possa effettivamente ottenere un riferimento a un caricatore di classi appropriato, cosa che potrebbe non essere possibile nel tuo caso.

    Thread.currentThread().setContextClassLoader(...);
    
  2. Assicurati che la classe sia caricata da un caricatore di classi superiore nella gerarchia.

  3. Serializza e deserializza l'oggetto. (Yuck!)

Esiste probabilmente un modo più appropriato per la tua situazione particolare.

Altri suggerimenti

Gli oggetti classe sono stati caricati in diversi classloader, quindi le istanze create da ciascuna classe sono considerate 'incompatibili'. Questo è un problema comune in un ambiente in cui vengono utilizzati molti caricatori di classi diversi e gli oggetti vengono passati in giro. Questi problemi possono sorgere facilmente in Java EE e negli ambienti del portale.

La trasmissione di un'istanza di una classe richiede che la Classe collegata all'oggetto da trasmettere sia uguale a quella caricata dal programma di caricamento della classe del thread corrente.

Ho riscontrato il problema A2AClassCastException durante il tentativo di creare un elenco di oggetti da XML utilizzando Apache Commons Digester.

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
}

Come detto sopra, la causa è che il digestore non usa lo stesso ClassLoader del resto del programma. Ho eseguito questo in JBoss e si è scoperto che commons-digester.jar non si trovava nella directory lib di JBoss, ma piuttosto nella directory lib di una webapp. Anche la copia del vaso in mywebapp / WEB-INF / lib ha risolto il problema. Un'altra soluzione è stata quella di lanciare digester.setClassLoader (MyTemplate.class.getClassLoader ()), ma in questo contesto sembra piuttosto una brutta soluzione.

Ho avuto lo stesso problema durante l'utilizzo di diverse istanze JBoss su macchine diverse. Peccato che non mi sia imbattuto in questo post prima.
Ci sono stati artefatti distribuiti su macchine diverse, due dei quali hanno dichiarato caricatori di classi con lo stesso nome. Ho cambiato uno dei nomi del caricatore di classi e tutto ha funzionato bene = & Gt; Fai attenzione a Copia & Amp; Paste!

Perché ClassCastException non menziona i programmi di caricamento classi coinvolti? - Penso che sarebbe un'informazione molto utile.
Qualcuno sa se ci sarà qualcosa di simile disponibile in futuro? La necessità di controllare i caricatori di classe di 20-30 artefatti non è così piacevole. O c'è qualcosa che mi è sfuggito nel testo dell'eccezione?

MODIFICA : ho modificato il file META-INF / jboss-app.xml e ho cambiato il nome del caricatore, l'idea è di avere un nome univoco. Al lavoro utilizziamo l'id artefatto (unico) combinato con la versione inserita da maven ({$ version}) durante la compilazione.
L'uso dei campi dinamici è solo facoltativo ma aiuta se desideri distribuire versioni diverse della stessa applicazione.

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

Puoi trovare alcune informazioni qui: https://community.jboss.org/wiki/ClassLoadingConfiguration

Ho avuto lo stesso problema e ho finalmente trovato una soluzione alternativa su java.net:

Copia tutti i org.eclipse.persistence jar file da glassfish4/glassfish/modules a WEB-INF/lib. Quindi vai in glassfish-web.xml e imposta class-delegate su false.

Ha funzionato per me!

Ho avuto un problema simile con JAXB e JBoss AS 7.1. Il problema e la soluzione sono descritti qui: javax.xml.bind.JAXBException: Classe *** né nessuna delle sue superclassi è nota in questo contesto . L'eccezione che è stata data era org.foo.bar.ValueSet non può essere trasmessa a org.foo.bar.ValueSet

Ho avuto lo stesso problema su un bean Wildfly, il bean stava restituendo un elenco di oggetti e ha un'interfaccia remota e locale. Ho usato l'interfaccia locale per errore ciò che funzionava bene fino al punto in cui provi a lanciare gli oggetti nell'elenco.

Interfaccia locale / remota:

public interface DocumentStoreService {

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

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

Il bean EJB:

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

L'involucro elastico corretto attorno al bean:

<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>

Nota $ Remote, puoi cambiarlo in $ Local e troverà l'interfaccia Local bene, ed eseguire anche i metodi senza alcun problema (da un'applicazione separata sullo stesso contenitore), ma gli oggetti del modello non sono marshalling e provengono da un caricatore di classi diverso se si utilizza l'interfaccia locale per errore.

Un'altra opzione:

Mi è successo nel weblogic, ma immagino che possa succedere anche in altri server - se lo fai (solo) " Pubblica " e quindi alcune delle tue classi vengono ricaricate. Invece fai & Quot; Clean & Quot; quindi tutte le classi verranno ricaricate insieme.

Ho avuto lo stesso problema con una ricerca EJB da un altro EJB. Ho risolto l'aggiunta di @Remote (MyInterface.class) alla configurazione della classe EJB

Aveva lo stesso my.package.MyClass cannot be cast to my.package.MyClass su WildFly 10.1 e, a quanto ho capito, ho fatto il contrario di quanto descritto da @Emil Lundberg nella sua risposta.

Ho aggiunto il modulo (che contiene my.package.MyClass) a my.war/WEB-INF/jboss-deployment-structure.xml come dipendenza

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

e rimosso il barattolo corrispondente da my.war/WEB-INF/lib, ricollocato la GUERRA e quindi il codice ha funzionato come previsto.

Pertanto, ci siamo assicurati che risolva il problema. Ora, dobbiamo assicurarci che il problema non si ripresenti, ad esempio, quando la versione aggiornata di WAR verrà assemblata e distribuita.

Per questo, nelle fonti di quei GUERRA , è necessario aggiungere <scope>provided</scope> per quei barattolo in pom.xml, in modo che quando my.war è riassemblato la prossima volta con il codice di correzione / miglioramento inserito, non raggrupperà questo barattolo in <=>.

Stavo riscontrando questo problema dopo aver aggiunto una dipendenza a spring-boot-devtools nel mio progetto Springboot. Ho rimosso la dipendenza e il problema è scomparso. La mia ipotesi migliore a questo punto è che <=> introduce un nuovo classloader e che causa il problema dei problemi di casting di classe tra diversi classloader in alcuni casi in cui il nuovo classloader non viene utilizzato da alcuni thread.

Riferimento: Un'eccezione per la mappa dozer correlata agli sviluppatori di avvio di Spring

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top