2013-01-21 80 views
3

我用完了想法,谷歌也沒有幫助。使用案例似乎很簡單,但它會因ClassCastException而失敗。我不知道我做錯了什麼。 有一個簡單的方法來返回匹配給定類別的第一個元素,看一看。lambdaJ和ClassCastException對簡單的選擇

private Category selectElement(List<? extends Category> results, Code code) { 
    return selectFirst(results, having(on(Category.class).getCode(), is(code))); 
} 

執行給人的堆棧此之上:

java.lang.ClassCastException: name.wilu.logic.report.utils.SheetLoader$Category$$EnhancerByCGLIB$$3a35aefc cannot be cast to net.sf.cglib.proxy.Factory 
at ch.lambdaj.proxy.ClassImposterizer.createProxy(ClassImposterizer.java:134) 
at ch.lambdaj.proxy.ClassImposterizer.imposterise(ClassImposterizer.java:101) 
at ch.lambdaj.proxy.ProxyUtil.createProxy(ProxyUtil.java:52) 
at ch.lambdaj.function.argument.ArgumentsFactory.createPlaceholder(ArgumentsFactory.java:68) 
at ch.lambdaj.function.argument.ArgumentsFactory.registerNewArgument(ArgumentsFactory.java:58) 
at ch.lambdaj.function.argument.ArgumentsFactory.createArgument(ArgumentsFactory.java:50) 
at ch.lambdaj.function.argument.ArgumentsFactory.createArgument(ArgumentsFactory.java:39) 
at ch.lambdaj.Lambda.on(Lambda.java:63) 

我同時使用lambdaJ用於操縱在休眠的控股實體持久化集合有同樣的問題。我放棄了假設代理對象(集合中的實體)已經是代理的問題。 看來我錯了,因爲Category和所有繼承的類都是pojos作爲結果轉換器傳遞到休眠狀態。

什麼可能是這種行爲的原因? 你有什麼想法嗎?

(我正在使用最新的lambdaj-2.4)。

添加到履行馬里奧的要求

代碼是一個簡單枚舉。 類別是不同類別的基類,它具有代碼字段。此外,它是公共靜態類,與所有繼承類相同(如果它很重要)。

我會盡力提供失敗的測試。

再次編輯以提供其他信息。 我的一位朋友看了一下代碼,並在這個問題上提出了新的亮點。

我會盡力從一開始就重現我們的演繹之路。

//鑑於

有分成兩個部分的應用程序,第一 - 基礎應用(保存模型文件)和Web應用程序(UI保持連接的文件,如支持豆類等)。 我們的類別和代碼是模型類,因此位於基礎應用程序中。然後我們有一個後臺bean服務於某些web邏輯,特別是bean或其協作者調用我們的select的

//當

我們到Web服務器上部署應用程序! JBoss在我的情況。類是由加載器讀取的,一些我並不知道發生的非常複雜的事情,都讓我的應用程序運行。 我做一些網絡行爲和該支持bean的方法被調用

selectFirst(results, having(on(Category.class).getCode(), is(code))); 

從應用程序的Web部件。

這裏是神奇的。 我們的Category.class和Code.class在應用程序加載時由UnifiedClassLoader加載。 我們在上(類別。類)方法和類的代理即將建成。一些非常糾結的邏輯被利用,要做到這一點,什麼是最重要的,代理儀器與

setThreadsCallbacks(Callback[]callbacks) 

方法,但Callback.class是從類加載器採取

aCategory.getClass.getClassLoader() 

因此它是一個類最初加載該類的加載器,即UnifiedClassLoader。 說完這一切乾淨一點,我們最後調用

getFirstInstance() 

,使用反射瀏覽Proxy類尋找: Proxy.getDeclaredMethod( 「setThreadsCallbacks」,新的Class [] {回調[]類。});

我忽略的事實,我不明白

new Class[]{ Callback[].class } 

是什麼在我們的例子中重要的是,Callback.class不提供BY UnifiedClassLoader。 應用程序在Web輪胎中執行,因此Callback.class的調用將由Web應用程序服務器。類加載器和Retured Callback.class將從前面提到的作爲段提到的setThreadsCallbacks functon。反思失敗了。

Category.class != Category.class //these two were provided by different classLoaders 

這就是爲什麼我無法提供失敗的測試。 (同一個類加載器)。

我懷疑有這種情況下的任何解決方案。

回答

1

我遇到過類似的問題。 (拋出同樣的異常:java.lang.ClassCastException:XXX $ Category $$ EnhancerByCGLIB $$ XXX無法轉換爲net.sf.cglib.proxy.Factory)

在我的情況下,它原來是一個問題重複(甚至三倍)CGLib庫。我們有如下:在JBoss中(4.2.3)庫

  • cglib.jar
  • CGLIB的nodep.jar在我們的應用程序的網絡庫(WAR文件)
  • labmdaj-2.4-與依賴性.jar在應用程序web庫中。

然後,使用Lambda.on(SomeClass.class)當我們到了這種方法在CGLIB的Enhancer類:

private static Method getCallbacksSetter(Class type, String methodName) throws NoSuchMethodException { 
     return type.getDeclaredMethod(methodName, new Class[]{ Callback[].class }); 
} 

其中methodName = "CGLIB$SET_THREAD_CALLBACKS" 和類型是我們SomeClass的由Enhancer包裹。

「CGLIB $ SET_THREAD_CALLBACKS」方法出現在包裝類型中,但getDeclaredMethod()返回null。看來在getDeclaredMethod()裏面有兩個net.sf.cglib.proxy.Callback.class實例的比較。他們不同,因爲一個是從cglib.jar(JBoss)加載的,另一個是從cglib-nodep.jar(webapp)加載的。

解決方案是刪除多餘的cglib-nodep.jar並將lambda-2.4-with-dependencies.jar替換爲lambda-2.4.jar。現在所有的CGLib類都從常見的地方加載並且問題消失了。