Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Weird problem when binding a dynamic list

INITIAL QUESTION (UPDATED BELOW)

I'm using an AutoPopulatingList list to instatiate an object invoking a constructor with some parameters. Something like the code below. I had used it before without any problems but I can't get it working now.

public class Tree {
    ...
    private List<Node> nodes = new AutoPopulatingList<Node>(new ElementFactory<Node>() {
        @Override
        public Node createElement(final int index) throws ElementInstantiationException {
             //call custom controller
             return new Node(index, ...other params);
        }       
    });
    ...
    //getters & setters
}

The object is mapped in a controller as a model attribute param (@ModelAttribute Tree). So I send in the form values like:

nodes[0].field1 = some value
nodes[1].field2 = other value

But when I send these parameters spring cannot instantiate the Node object because it's looking for a constructor without params for Node object, and it throws an Exception like the following:

org.springframework.beans.NullValueInNestedPathException: Invalid property 'nodes' of bean class [...Node]: Could not instantiate property type [...Node] to auto-grow nested property path: java.lang.InstantiationException: ...Node.()

If I add a constructor without params to Node class there is no error, but when I send nodes[0] it is invoked Node() instead of using the ElementFactory provided.

The weird thing is that if I do in the controller treeObject.getNodes().get(0), the constructor invoked is the one with params (as it should be).

I'm using Spring 3.0.4.RELEASE.

Does anybody knows why can this be happening? Can this be a bug?

Thanks.


UPDATE

I have build a custom implementation of a List similar to AutoPopulatingList to check if this was a problem of AutoPopulatingList, but it happens the same behaviour. The implementation just overrides:

public Node get(int index) {
    //here just creates the object it it doesn't exist in the position
}

So the problem is why when I do in a controller:

public String controllerMethod(
@ModelAttribute Tree tree, BindingResult result, Model model){
     ...
}

and I send nodes[0].something as there isn't any object in the position 0 of index it has to instance the object. But the problem is that it is invoked Node() constructor before invoking tree.get(0). So, Why does Spring invokes the default constructor? How can I force it to use tree.get(0) to instance the object instead of Node()?

like image 750
Javi Avatar asked Jan 11 '11 12:01

Javi


1 Answers

I've solved it by disabling the autogrownestedpaths in the binder, so this allows Autopopulating list will take care of auto-growing with its own factory.

@InitBinder
public void initBinder(WebDataBinder binder){
    binder.setAutoGrowNestedPaths(false);
}
like image 145
Javi Avatar answered Oct 04 '22 06:10

Javi