Adrian Ber
Adrian Ber

Reputation: 21370

Spring binding and form field naming

I have the following beans:

class User {
    private List<Address> addresses;

    // ... getter and setter for addresses follows
}

class Address {
    private String street, city;

    // ... getters and setters follows 
}

This is the controller

@RequestMapping(value = { "/doSomething" })
public String doSomething(@ModelAttribute User user, BindingResult result, Model model) {
    // ...
}

And the form could be something like

<form>
    <input type="text" name="addresses[].street" />
    <input type="text" name="addresses[].city" />
    ...
</form>

But I get the following error

Request processing failed; nested exception is org.springframework.beans.InvalidPropertyException: Invalid property 'addresses[]' of bean class [User]: Invalid index in property path 'addresses[]'; nested exception is java.lang.NumberFormatException: For input string: ""
java.lang.NumberFormatException: For input string: ""
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) ~[na:1.8.0_31]
at java.lang.Integer.parseInt(Integer.java:592) ~[na:1.8.0_31]
at java.lang.Integer.parseInt(Integer.java:615) ~[na:1.8.0_31]
at org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:989) ~[spring-beans-4.1.2.RELEASE.jar:4.1.2.RELEASE]

How should I name the fields in a form so that Spring will be able to do the binding?

Upvotes: 1

Views: 839

Answers (2)

Adrian Ber
Adrian Ber

Reputation: 21370

I got it. The problem is that the property is missing an index. Spring can bind multiple properties (collection, lists, arrays) to request parameters, but the names must include an index.

So the form must be

<form>
    <input type="text" name="addresses[0].street" />
    <input type="text" name="addresses[0].city" />

    <input type="text" name="addresses[1].street" />
    <input type="text" name="addresses[1].city" />
    ...
</form>

Instead of 0, 1 ... you can use ${iterationStatus.index} in Thymeleaf (server side) or {{$index}} in Angular (client side).

Upvotes: 1

Stef
Stef

Reputation: 2683

The error I think is because it can't convert [""] into [number] and thus it can't locate what element from that array it should access.

For collections you either use ngRepeat to loop through or use explicit indexes. In most cases you'll want to loop, so here's an example of that:

<form ng-repeat="address in user.addresses">
    <input type="text" ng-model="address.street" />
    <input type="text" ng-model="address.city" />
    ...
</form>

Note that this works if you submit the form using angular (thus, rather than allowing for the standard HTML submit, you submit the scope object that Angular is modifying due to the ng-model mapping.

Upvotes: 0

Related Questions