2010-04-10 11 views
5

Widzę dziwny komunikat o błędzie i szukam pomysłów na temat tego, jaki może być problem. Jestem trochę nowy w używaniu WZP.Burza mózgów: Dziwny problem JPA, prawdopodobnie problem z wersją klasu lub słoika?

Mam aplikację, w której używam Spring Managera Entity Factory (LocalContainerEntityManagerFactoryBean), EclipseLink jako mój dostawca ORM, podłączony do MySQL DB i zbudowany z Maven. Nie jestem pewien, czy to ma znaczenie .....

Po wdrożeniu tej aplikacji na Glassfish aplikacja działa zgodnie z oczekiwaniami.

Problem polega na tym, że utworzyłem zestaw samodzielnych testów jednostkowych do uruchamiania poza Glassfish, które nie działają poprawnie. Pojawia się następujący błąd (Mam edycji nazwy klas trochę)

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

Obiekt nie może być oddane do klasy tego samego typu? Jak to możliwe?

Oto fragment kodu, który jest w błędzie

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; 

Wcześniej miałem ten kod, który wyprodukował ten sam błąd:

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; 

Ten kod jest kwestia jest taka sama, że ​​mam wdrożone na serwerze.

oto najgłębsza wyjątek czy to pomaga

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 

Zgaduję, że istnieje jakiś słoik Używam w GlassFish, który jest inny niż te, które używam w teście. Sprawdziłem wszystkie słoiki, które wymieniłem jako "dostarczone" i jestem pewien, że wszystkie są takie same z Glassfish.

Daj mi znać, jeśli wcześniej widziałeś ten dziwny problem lub pomysły na jego poprawienie.

Odpowiedz

5

Może to być również problem z ładowaniem klas. Ta sama definicja klasy, ładowana przez dwa różne ładowniki klas, jest postrzegana przez JVM jako różne klasy.

można spróbować tego, aby uzyskać informacje na temat ładowarki klasy w grze:

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); 
} 

Zamiast System.out.println można oczywiście użyć połączenia z wybranym ramach rejestrowania.

Oto a series of articles z dodatkowymi informacjami na temat ładowania klas.

+0

Tak OK, to wydaje się być problemem. Oto wynik: ładowarka klasa MyEntity jest ładowarka klasa [email protected] MyEntity obiektu jest org.springfr[email protected]16089a5 Teraz jak to naprawić ??? Zamierzam zagłębić się w artykuły, z którymi się łączyłeś. – Vinnie

+1

@Vinnie Niestety nie znam używanych narzędzi, więc nie mogę zaoferować bardziej konkretnej pomocy. Powodzenia - będziesz go potrzebować ... –

+1

OK, to prawdopodobnie błąd debiutanta, ale twoja sugestia (i rewelacja o użyciu różnych Classloaderów lokalnie) doprowadziły do ​​praktycznego rozwiązania. Widząc, że w grze są różne Classloadery, pomyślałem, że Spring LocalContainerEntityManagerFactoryBean nie był właściwym wyborem podczas moich testów jednostkowych. Przełączyłem się na LocalEntityManagerFactoryBean (co również oznaczało, że potrzebowałem nowej jednostki wytrwałości, ponieważ nie mogłem wstrzyknąć DataSource) i rzeczy wydają się działać lokalnie teraz. Dzięki za pomoc! – Vinnie

1

To wyraźnie pachnie numerem ClassLoader (być może ze względu na konieczność tkania EclipseLink). Czy używasz LoadTimeWeaver? Czy są skonfigurowane jakieś elementy JavaFace? Czy problem występuje w linii poleceń pod Maven? w twoim IDE? Proszę o wyjaśnienie.

+0

Dobra uwaga na temat tkania, miałem zamiar wspomnieć o tym w pytaniu. Używam org.springframework.context.weaving.DefaultContextLoadTimeWeaver w Glassfish i org.springframework.instrument.classloading.SimpleLoadTimeWeaver w moich testach. Nie byłem pewien, którego użyć, więc wybrałem jedną, która wydawała się działać. – Vinnie

+0

BTW - Nie mam skonfigurowanego żadnego javaagenta. A problem występuje zarówno z linii poleceń maven, jak i pochodził z IDE. Serwer Glassfish to jedyny obszar, w którym nie widzę problemu. – Vinnie