Pergunta

Eu tenho 2 projetos Java diferentes, um tem 2 classes: dynamicbeans.DynamicBean2 e dynamic.Validator.

Por outro Object

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

Eu então vou em frente e crio um Validator objeto usando validatorClass.newInstance() e armazenar validator Então eu crio um objeto de feijão também usando beanClass.newInstance() e adicione -o à sessão.

portletRequest.setAttribute("DynamicBean2", bean);

Durante o ciclo de vida do Form Projeto, eu ligo validator.validate() que carrega o objeto Bean criado anteriormente na sessão (estou executando o WebSphere Portal Server). Quando tento lançar esse objeto de volta em um DynamicBean2 Ele falha com uma classe de classe.

Quando eu puxo o objeto de volta da sessão usando

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

e verifique a classe usando .getClass() eu recebo dynamicbeans.DynamicBean2. Esta é a aula que eu quero lançá -la, no entanto, quando tento obter a ClassCastException.

Alguma razão pela qual estou recebendo isso?

Foi útil?

Solução

Não estou acompanhando sua descrição do fluxo do programa, mas geralmente quando você obtém o ClassCastExceptions, não pode explicar que carregou a classe com um carregador de classe e tente lançá -lo para a mesma classe carregada por outro carregador de classe. Isso não funcionará - eles são representados por dois objetos de classe diferentes dentro da JVM e o elenco falhará.

Há um Artigo sobre o carregamento de classe no WebSphere. Não posso dizer como isso se aplica ao seu aplicativo, mas há várias soluções possíveis. Eu posso pensar em pelo menos:

  1. Altere o carregador de classe de contexto manualmente. Requer que você possa realmente obter uma referência a um carregador de classe apropriado, o que pode não ser possível no seu caso.

    Thread.currentThread().setContextClassLoader(...);
    
  2. Verifique se a classe é carregada por um carregador de classe mais alto na hierarquia.

  3. Serialize e desserialize o objeto. (Que nojo!)

Provavelmente, existe uma maneira mais apropriada para sua situação específica.

Outras dicas

Os objetos da classe foram carregados em diferentes carregadores de classe; portanto, as instâncias criadas em cada uma das classes são vistas como 'incompatíveis'. Esse é um problema comum em um ambiente em que existem muitos carregadores de classe diferentes e objetos estão sendo transmitidos. Esses problemas podem surgir facilmente nos ambientes Java EE e do portal.

Ficar uma instância de uma classe exige que a classe vinculada ao objeto que está sendo lançada seja a mesma que a carregada pelo carregador de classe de contexto de encadeamento atual.

Eu obtive o problema do A2AclassCastException ao tentar criar uma lista de objetos do XML usando o 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
}

Como afirmado acima, a causa é que o digestor não usa o mesmo carregador de classe que o restante do programa. Eu corri isso em Jboss, e aconteceu que o Commons-Digester.jar não estava no diretório Lib de Jboss, mas sim no diretório Lib do WebApp. Copiar o frasco no mywebapp/web-inf/lib também resolveu o problema. Outra solução foi o Casll Digester.SetClassLoader (myTemplate.class.getclassloader ()), mas isso parece uma solução bastante feia nesse contexto.

Eu tive o mesmo problema ao usar várias instâncias do JBoss em diferentes máquinas. Para ruim, não tropecei nesse post anteriormente.
Havia artefatos implantados em diferentes máquinas, duas delas declararam carregadeiras de classe com nome idêntico. Mudei um dos nomes do carregador de classe e tudo funcionou bem => Cuidado com a cópia e a pasta!

Por que a ClassCastException não mencionou os carregadores de classe envolvidos? - Eu acho que isso seria uma informação muito útil.
Alguém sabe se haverá algo assim disponível no futuro? Precisando verificar os carregadores de classe de 20 a 30 artefatos não é tão agradável. Ou há algo que perdi no texto de exceção?

EDITAR: Editei o arquivo meta-inf/jboss-app.xml e mudei o nome do carregador, a idéia é ter um nome exclusivo. No trabalho, usamos o ID do artefato (exclusivo) combinado com a versão inserida pelo maven ({$ versão}) durante a compilação.
O uso de campos dinâmicos é apenas opcional, mas ajuda se você deseja implantar versões diferentes do mesmo aplicativo.

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

Você pode encontrar algumas informações aqui: https://community.jboss.org/wiki/classLoadingConfiguration

I had the same issue, and I finally found a workaround on java.net :

Copy all org.eclipse.persistence jar files from glassfish4/glassfish/modules to WEB-INF/lib. Then go in your glassfish-web.xml, and set class-delegate to false.

Worked for me !

I had a similar issue with JAXB and JBoss AS 7.1. The issue and solution are described here: javax.xml.bind.JAXBException: Class *** nor any of its super class is known to this context. The exception that was given was org.foo.bar.ValueSet cannot be cast to org.foo.bar.ValueSet

I had the same issue on a wildfly EJB, The EJB was returning a list of Objects and has an remote and a local interface. I used the Local interface by mistake what was working just fine up until the point you try to cast the objects in the list.

Local/Remote interface:

public interface DocumentStoreService {

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

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

The EJB bean:

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

The correct spring wrapper around the 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>

Note the $Remote, You can change this to $Local and it will find the Local interface just fine, and also execute the methods without any issue (from a separate application on the same container), but the model objects are not marshaled and are from a different class loader if you use the local interface by mistake.

Another option:

Happened to me in weblogic, but I guess it can happen in other servers as well - if you do (just) "Publish" and therefor some of your classes are re-loaded. Instead do "Clean" so all the classes will re-loaded together.

I had same problem with an EJB lookup from another EJB. I solved adding @Remote(MyInterface.class) to EJB class configuration

Had the same my.package.MyClass cannot be cast to my.package.MyClass on WildFly 10.1 and, as I understand, I did the opposite to what @Emil Lundberg described in his answer.

I have added the module (which contains my.package.MyClass) to my.war/WEB-INF/jboss-deployment-structure.xml as a dependency

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

and removed the corresponding jar from my.war/WEB-INF/lib, re-deployed the WAR and then the code worked as expected.

Thus, we made sure it solves the issue. Now, we need to make sure the issue won't come back, for example, when the updated version of WAR will be assembled and deployed.

For this, in the sources of those WAR, it is required to add <scope>provided</scope> for those jar in pom.xml, so that when my.war is re-assembled next time with the fix/enhancement code injected, it will not bundle this jar into my.war/WEB-INF/lib.

I was getting this problem after adding a dependency to spring-boot-devtools in my Springboot project. I removed the dependency and the problem went away. My best guess at this point is that spring-boot-devtools brings in a new classloader and that causes the issue of class casting problems between different classloaders in certain cases where the new classloader is not being used by some threads.

Reference: A dozer map exception related to Spring boot devtools

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top