[英]java.lang.ClassCastException: $Proxy99 cannot be cast
[英]java.lang.ClassCastException: $Proxy96 cannot be cast to ticket.app.DatesFacade
我正在將代碼輸入到在Ubuntu盒子上運行的Hudson Server中,以便在代碼上運行一些Code Metrics(Sonar)和Cobertura。 該項目從Glassfish3.1開始,使用Maven3(用Java,JSF 2.0編寫)並使用OracleXE數據庫(無關)。
嘗試在我的JUnit測試中創建Facade實例時拋出錯誤。 當我從Netbeans運行測試時,它們運行良好,但是當Hudson在其上進行自動構建時,出現此錯誤:
java.lang.ClassCastException: $Proxy96 cannot be cast to ticket.app.DatesFacade
at ticket.app.EventsControllerTest.setUp(EventsControllerTest.java:60)
at junit.framework.TestCase.runBare(TestCase.java:128)
at junit.framework.TestResult$1.protect(TestResult.java:106)
at junit.framework.TestResult.runProtected(TestResult.java:124)
at junit.framework.TestResult.run(TestResult.java:109)
at junit.framework.TestCase.run(TestCase.java:120)
at junit.framework.TestSuite.runTest(TestSuite.java:230)
at junit.framework.TestSuite.run(TestSuite.java:225)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:616)
at org.apache.maven.surefire.junit.JUnitTestSet.execute(JUnitTestSet.java:207)
at org.apache.maven.surefire.junit.JUnit3Provider.executeTestSet(JUnit3Provider.java:107)
at org.apache.maven.surefire.junit.JUnit3Provider.invoke(JUnit3Provider.java:79)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:616)
at org.apache.maven.surefire.booter.ProviderFactory$ClassLoaderProxy.invoke(ProviderFactory.java:103)
at $Proxy0.invoke(Unknown Source)
at org.apache.maven.surefire.booter.SurefireStarter.invokeProvider(SurefireStarter.java:145)
at org.apache.maven.surefire.booter.SurefireStarter.runSuitesInProcess(SurefireStarter.java:87)
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:69)
Hudson服務器不是從JBoss運行的,而是從Tomcat運行的。 我添加這個細節是因為當我使用Google這個錯誤時,除了JBoss錯誤,我什么都沒有發現,這說明在WAR和EAR文件中都引用了Facade。
編輯:這就是我當前創建Facade實例的方式(通過Netbeans GF3.1運行測試時,它可以正常工作):
Map properties = new HashMap();
properties.put(EJBContainer.MODULES, new File("target/classes"));
properties.put("org.glassfish.ejb.embedded.glassfish.configuration.file", "server/config/domain.xml");
properties.put("oracle.jdbc.OracleDriver", "server/lib/ojdbc14.jar");
ejbContainer = EJBContainer.createEJBContainer(properties);
ctx = ejbContainer.getContext();
EventsFacade instance = (EventsFacade)ctx.lookup("java:global/classes/EventsFacade");
編輯:我的活動
@Stateful
public class EventsFacade extends AbstractFacade<Events> {
@PersistenceContext(unitName = "tickets_AppTicket_war_1.0-SNAPSHOTPU")
private EntityManager em;
protected EntityManager getEntityManager() {
return em;
}
public EventsFacade() {
super(Events.class);
}
}
編輯 :和..我的AbstractFacade完整:
public abstract class AbstractFacade<T> {
private Class<T> entityClass;
public AbstractFacade(Class<T> entityClass) {
this.entityClass = entityClass;
}
protected abstract EntityManager getEntityManager();
public void create(T entity) {
getEntityManager().persist(entity);
}
public void edit(T entity) {
getEntityManager().merge(entity);
}
public void remove(T entity) {
getEntityManager().remove(getEntityManager().merge(entity));
}
public T find(Object id) {
return getEntityManager().find(entityClass, id);
}
public List<T> findAll() {
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
cq.select(cq.from(entityClass));
return getEntityManager().createQuery(cq).getResultList();
}
public List<T> findRange(int[] range) {
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
cq.select(cq.from(entityClass));
javax.persistence.Query q = getEntityManager().createQuery(cq);
q.setMaxResults(range[1] - range[0]);
q.setFirstResult(range[0]);
return q.getResultList();
}
public int count() {
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
javax.persistence.criteria.Root<T> rt = cq.from(entityClass);
cq.select(getEntityManager().getCriteriaBuilder().count(rt));
javax.persistence.Query q = getEntityManager().createQuery(cq);
return ((Long) q.getSingleResult()).intValue();
}
}
編輯:創建新的接口:
@Local
public interface EventsInterface<Events> {
int count();
void create(Events entity);
void edit(Events entity);
Events find(Object id);
List<Events> findAll();
List<Events> findRange(int[] range);
void remove(Events entity);
}
更改:事件立面聲明:
public class EventsFacade extends AbstractFacade<Events> implements EventsInterface<Events> {
編輯:創建新接口后,在IDE中收到代理錯誤后,輸出開始顯示:
Field Name == intfClass
Field == interface ticket.app.EventsInterface
Field Name == containerId
Field == 85313541807800321
Field Name == delegate
Field == com.sun.ejb.containers.EJBLocalObjectInvocationHandler@72b0f2b2
Field Name == isOptionalLocalBusinessView
Field == false
通常,這意味着在對象周圍有代理(並且代理基於接口)的情況下,您是按對象的類而不是其接口引用對象。
解決方案是通過其接口引用該對象。 我猜想EventsFacade
具有Local
和/或Remote
接口。 嘗試使用它。 如果沒有接口,請創建一個接口,這是一個好習慣。 在接口中定義所有公共方法。
更新:看來,這可能與您使用的嵌入式玻璃魚有關。 由於您無法使用調試器進行調試,因此可以跟蹤該問題:使用java.lang.reflect.Proxy.getInvocationHandler(object)
。 然后列出返回對象的所有字段。 (您現在必須刪除演員表,並從上下文中簡單地將其作為Object
)。 就像是:
Object ic = Proxy.getInvocationHandler(facade);
Field[] fields = ic.getClass().getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
System.out.println(field.getName() + "=" + field.get(ic);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.