If you wand to use more than one ModelAttribute, you have to create a wrapper object, which holds an instance of each ModelAttribute. In your case I would create a wrapper object called "FormModel" which holds an instance of Address and an instance of a BillingAddress.
class FormModel {
private Address address;
private BillingAddress billingAddress;
// Getters and Setters
}
Now use FormModel as your ModelAttribute.
In your Form you can define your input-elements like:
<input name="address.address" ..>
<input name="billingAddress.address" ..>
Controller:
@RequestMapping(value = "/save", method = RequestMethod.POST)
public String save(Model model, @ModelAttribute() FormModel formModel) {
// process formModel.getAddress()
// process formModel.getBillingAddress()
return "redirect:home";
}
If you use custom validators for Address and BillingAddress, you also have to create a FormModelValidator that calls the AddressValidator and BillingAddressValidator:
public class FormModelValidator implements Validator {
private final AddressValidator addressValidator;
private final BillingAddressValidator billingAddressValidator;
public FormModelValidator(AddressValidator addressValidator,
BillingAddressValidator billingAddressValidator) {
this.addressValidator = addressValidator;
this.billingAddressValidator = billingAddressValidator;
}
public boolean supports(Class<?> clazz) {
return FormModel.class.equals(clazz);
}
public void validate(Object target, Errors errors) {
FormModel formModel = (FormModel) target;
try {
errors.pushNestedPath("address");
ValidationUtils.invokeValidator(this.addressValidator,
formModel.getAddress(), errors);
} finally {
errors.popNestedPath();
}
try {
errors.pushNestedPath("billingAddress");
ValidationUtils.invokeValidator(this.billingAddressValidator,
formModel.getBillingAddress(), errors);
} finally {
errors.popNestedPath();
}
}
}