LambdaJ ArgumentConversionException unable to convert the placeholder null in a valid argument

I got recently exited about LambdaJ and the possibility to use functional programming style in Java (similar to for example jQuery each()). The main promise is to make the traditionally very cumbersome Java’s Collection iteration look nicer (use a one-liner instead of 5-7 lines of procedural for -loop code), like this:

List sortedByAgePersons = sort(persons, on(Person.class).getAge());

instead of

List sortedByAgePersons = new ArrayList(persons);
Collections.sort(sortedByAgePersons, new Comparator() {
  public int compare(Person p1, Person p2) {
    return Integer.valueOf(p1.getAge()).compareTo(p2.getAge());
  }
});

But then I stuck to the following error message every time that I tried to use the basic Lambda.select(), Lambda.filter() or any other function that required reference to the LambdaJ’s Argument or on() -syntax. For example

filter(myMap, on(MyClass.class).field());

LambdaJ ArgumentConversionException unable to convert the placeholder null in a valid argument

This throws an exception LambdaJ ArgumentConversionException unable to convert the placeholder like this:

ch.lambdaj.function.argument.ArgumentConversionException: Unable to convert the placeholder null in a valid argument
	at ch.lambdaj.function.argument.ArgumentsFactory.actualArgument(ArgumentsFactory.java:76)
	at ch.lambdaj.function.convert.ArgumentConverter.(ArgumentConverter.java:29)
	at ch.lambdaj.Lambda.extract(Lambda.java:1035)
	at ch.lambdaj.Lambda.count(Lambda.java:264)

According to LambdaJ author Mario Fusco the issue is caused by Java’s inability to create proxy methods of anything that is declared final. The most offending final methods and classes include Java’s String implementation (a major hindrance) and in my case Wicket’s FeedbackMessage classes. See Usage of final and private discouraged

The Solution

However, we are not yet out-of-luck, if you you make some hacks to overcome the problem. Let’s go through the possible situations

1. Final Class such as java.lang.String

This is the most difficult one to circumvent, since you cannot create any subclass wrappers. You have two basic options: fork the source code of the dependent library or framework, and re-declare the final class as non-final. You need to recompile the whole framework, and you end up with a non-maintained fork. If you are lucky, the library’s developers might reconsider the usage of final, and incorporate your change to the main branch.

2. Final Methods on non-final class such as Apache Wickets FeedbackErrorMessage

If you are lucky, only the methods and properties have been declared as final, not the whole class such as Apache Wicket FeedbackMessage. In this case you can create a non-final wrapper for the intended class by extending it. For example:

 import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.List;
 import org.apache.wicket.Component;
 import org.apache.wicket.feedback.FeedbackMessage;
 public class NonFinalFeedbackMessage extends org.apache.wicket.feedback.FeedbackMessage {
    private Serializable nonFinalMessage;
    public NonFinalFeedbackMessage(Component reporter, Serializable message, int level) {
        super(reporter, message, level);
        this.nonFinalMessage = message;
    }
    public Serializable getNonFinalMessage() {
        return this.nonFinalMessage;
    }
 }

3. Final methods with private properties

However, in this case there was also a second hindrance – the Wicket’s FeedbackMessage.message is also declared as private, and thus is not visible to the subclass. You need to create a new property wrapper for it which is initialized by the constructor:

    protected Serializable nonPrivateMessage;
    protected int nonPrivateLevel;
    public NonFinalFeedbackMessage(Component reporter, Serializable message, int level) {
        super(reporter, message, level);
        this.nonPrivateMessage = message;
        this.nonPrivateLevel = level;
    }
    public Serializable getNonFinalMessage() {
        return this.nonPrivateMessage;
    }
    public int getNonFinalLevel() {
        return this.nonPrivateLevel;
    }

In my case to get the LamdaJ.on() and select() to work, I had to also create a non-final shallow copy of the original final FeedbackMessage -collection:

    
 public static List copyAsNonFinal(List> feedbackMessages) {
        List nonFinalMessages = new ArrayList();
        for (Object m : feedbackMessages) {
            NonFinalFeedbackMessage nfmsg = new NonFinalFeedbackMessage((FeedbackMessage) m);
            nonFinalMessages.add(nfmsg);
        }
        return nonFinalMessages;
    }

After this it was possible to use LambdaJs Arguments to iterate over non-final collections:

 
 List nonFinalMessages = filter(
	having(on(NonFinalFeedbackMessage.class).getNonFinalLevel(),
		greaterThanOrEqualTo(FeedbackMessage.ERROR)),
	NonFinalFeedbackMessage.cloneAsNonFinal(feedbackMessages));

I have to admit that the non-final wrapper subclass is a bit uggly and adds more code than the basic for-loop iteration of the same thing. I need to check next if there would be possibilities to use Reflection or to create/find some generic utilities to do the same.