I run out of ideas, Google also did not help. Use case seems to be trivial but it fails with ClassCastException. I don't know what I am doing wrong.
There's a simple method to return first element matching a given category, take a look.
private Category selectElement(List<? extends Category> results, Code code) {
return selectFirst(results, having(on(Category.class).getCode(), is(code)));
}
Execution gives this top of the stack:
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)
I had the same problem while using lambdaJ for manipulation over hibernate's persistent collections holding entities. I gave up assuming there might be some problem with proxying objects (entities in collection) that already are proxies.
It seems I were wrong because Category and all inherited classes are pojos passsed to the hibernate as a result transformer.
What might be a reason of such behavior?
Do you have any idea?
(I'm using the most recent lambdaj-2.4).
Added to fulfill Mario's request
Code is a simple enum.
Category is a base class for different categories, it has code field. Moreover, it's public static class, same as all inheriting classes (if it matters).
I'll try to provide failing test.
Editing again to provide additional info.
A friend of mine took a look on the code and put a fresh bright light on the issue.
I will try to reproduce our path of deduction from the very beginning.
// Given
There's an application divided into two parts, the first - base application (keeps model files) and the web application (keeps UI connected files like backing beans and so forth).
Our category and code are model classes thus are located in base application. We have then a backing bean serving for the purpose of some web logic and particularly that bean or its collaborator calls our select.
// When
We're deploying application to a web server! JBoss in my case. Classes are read by loaders, some pretty complicated things that I'm not aware of happen, all to have my application running.
I do some web action and that backing bean's method is called
selectFirst(results, having(on(Category.class).getCode(), is(code)));
from web part of application.
Here comes the magic.
Our Category.class and Code.class were loaded by UnifiedClassLoader on application load.
We're in on(Category.class) method and the proxy of Category is going to be built. Some really tangled logic is harnessed to do that, What's the most important, proxy is instrumented with
setThreadsCallbacks(Callback[]callbacks)
method, but Callback.class is taken from that class loader
aCategory.getClass.getClassLoader()
thus it is a class loader that initially loaded that class, the UnifiedClassLoader .
Having all this done cleanly we finally call
getFirstInstance()
that using reflection browses Proxy class seeking for:
Proxy.getDeclaredMethod("setThreadsCallbacks", new Class[]{ Callback[].class });
I omit the fact, I do not understand
new Class[]{ Callback[].class }
What's important in our case is that Callback.class is NOT PROVIDED BY UnifiedClassLoader.
Applicaiton is executed in a web tire so a call for Callback.class will be server by web app. class loader and retured Callback.class will dffer from what was previously put as an argment for mentioned setThreadsCallbacks functon. Reflection fails cruelly.
Category.class != Category.class //these two were provided by different classLoaders
That is why I was not able to provide failing test. (same class loader).
I doubt there's any solution for that case.