2010-04-10 4 views
5

Ich sehe eine seltsame Fehlermeldung und suche nach Ideen, was das Problem sein könnte. Ich bin irgendwie neu in der Verwendung der JPA.Brainstorming: Sonderbares JPA-Problem, möglicherweise Klassenpfad- oder Jarversionsproblem?

Ich habe eine Anwendung, wo ich Spring Entity Manager Factory (LocalContainerEntityManagerFactoryBean), EclipseLink als mein ORM-Provider, mit einer MySQL-DB verbunden und mit Maven gebaut. Ich bin nicht sicher, ob irgendetwas davon von Bedeutung ist.

Wenn ich diese Anwendung auf Glassfish bereitstellen, funktioniert die Anwendung wie erwartet.

Das Problem ist, ich habe eine Reihe von eigenständigen Komponententests außerhalb von Glassfish erstellt, die nicht ordnungsgemäß funktionieren. Ich erhalte die folgende Fehlermeldung (ich die Klassennamen ein wenig bearbeitet haben)

com.xyz.abc.services.persistence.entity.MyEntity cannot be cast to com.xyz.abc.services.persistence.entity.MyEntity 

Das Objekt kann nicht auf eine Klasse des gleichen Typs gegossen werden? Wie kann das sein?

Hier ist ein Ausschnitt aus dem Code, den

Query q = entityManager.createNamedQuery("MyEntity.findAll"); 
List entityObjects = q.getResultList(); 
for (Object entityObject: entityObjects) { 
    com.xyz.abc.services.persistence.entity.MyEntity entity = (com.xyz.abc.services.persistence.entity.MyEntity) entityObject; 

Zuvor fehlerhaft ist, ich diesen Code hatte, die den gleichen Fehler erzeugt hat:

CriteriaQuery cq = entityManager.getCriteriaBuilder().createQuery(); 
cq.select(cq.from(com.xyz.abc.services.persistence.entity.MyEntity.class)); 
List entityObjects = entityManager.createQuery(cq).getResultList(); 
for (Object entityObject: entityObjects) { 
    com.xyz.abc.services.persistence.entity.MyEntity entity = (com.xyz.abc.services.persistence.entity.MyEntity) entityObject; 

Dieser Code Frage ist, ist die gleiche, dass ich auf dem Server bereitgestellt.

Hier ist die innerste Ausnahme, wenn es

Caused by: java.lang.ClassCastException: com.xyz.abc.services.persistence.entity.MyEntity cannot be cast to com.xyz.abc.services.persistence.entity.MyEntity 
    at com.xyz.abc.services.persistence.entity.factory.MyEntityFactory.createBeans(MyEntityFactory.java:47) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
    at java.lang.reflect.Method.invoke(Method.java:597) 
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:115) 
    ... 37 more 

hilft Ich vermute, dass es einige jar ich in Glassfish bin mit, die als die andere ist, ich in Test bin. Ich habe mir alle Gläser angesehen, die ich als "zur Verfügung gestellt" aufgeführt habe, und ich bin mir ziemlich sicher, dass es sich um dieselben von Glassfish handelt.

Lassen Sie mich wissen, wenn Sie dieses seltsame Problem vorher gesehen haben, oder irgendwelche Ideen, es zu korrigieren.

Antwort

5

Dies könnte auch ein Klassenladeproblem sein. Dieselbe Klassendefinition, die von zwei verschiedenen Klassenladern geladen wird, wird von der JVM als unterschiedliche Klassen angesehen. Verwendung Anrufe an Ihre bevorzugte Logging-Framework

Query q = entityManager.createNamedQuery("MyEntity.findAll"); 
List entityObjects = q.getResultList(); 

ClassLoader loader1 = 
    com.xyz.abc.services.persistence.entity.MyEntity.getClass().getClassLoader(); 
System.out.println("MyEntity's class loader is " + loader1); 
for (Object entityObject: entityObjects) { 
    ClassLoader loader2 = entityObject.getClass().getClassLoader(); 
    System.out.println("Class loader of entity " + entityObject + " is " + loader2); 
} 

Statt System.out.println Sie könnten natürlich:

Sie könnten versuchen, diese Informationen zu den Klassenlader in das Spiel zu bekommen.

Hier ist a series of articles mit weiteren Details zum Laden von Klassen.

+0

Ja OK, das scheint ein Problem zu sein. Hier ist die Ausgabe: MyEntity der Class Loader ist [email protected] MyEntity Objekt der Klassenlader wird org.springfr[email protected]16089a5 Nun, wie es zu beheben ??? Ich werde mir die Artikel ansehen, mit denen Sie verlinkt sind. – Vinnie

+1

@Vinnie Leider bin ich nicht vertraut mit den Tools, die Sie verwenden, daher kann ich keine konkretere Hilfe anbieten. Viel Glück - Sie werden es brauchen ... –

+1

OK, das ist wahrscheinlich ein Anfängerfehler, aber Ihr Vorschlag (und die Enthüllung über die Verwendung von verschiedenen Classloadern lokal) führte zu einer praktikablen Lösung. Als ich sah, dass verschiedene Classloader im Spiel waren, musste ich denken, dass Spring LocalContainerEntityManagerFactoryBean nicht die richtige Wahl für meine Unit-Tests war. Ich wechselte zu LocalEntityManagerFactoryBean (was auch bedeutete, dass ich eine neue Persistenzeinheit brauchte, da ich die DataSource nicht injizieren konnte) und die Dinge scheinen jetzt lokal zu arbeiten. Danke für die Hilfe! – Vinnie

1

Dies riecht eindeutig ein ClassLoader Problem (vielleicht aufgrund der Weberei von EclipseLink benötigt). Verwenden Sie die LoadTimeWeaver? Haben Sie irgendwelche Java-Agenten konfiguriert? Tritt das Problem in der Befehlszeile unter Maven auf? in deiner IDE? Bitte klären Sie.

+0

Guter Punkt über das Weben, ich wollte das in der Frage erwähnen. Ich verwende org.springframework.context.weaving.DefaultContextLoadTimeWeaver in Glassfish und org.springframework.instrument.classloading.SimpleLoadTimeWeaver in meinen Tests. Ich war mir nicht sicher, welches ich verwenden sollte, also wählte ich nur eines aus, das zu funktionieren schien. – Vinnie

+0

BTW - Ich habe keinen Java-Agent konfiguriert. Und das Problem tritt sowohl von der Maven-Kommandozeile als auch von der IDE auf. Der Glassfish-Server ist der einzige Bereich, in dem ich das Problem nicht sehe. – Vinnie

Verwandte Themen