Контекст
У меня есть простая ассоциация между двумя сущностями - Category
и Email
(NtoM). Я пытаюсь создать веб-интерфейс для просмотра и управления ими. Чтобы просмотреть категорию и добавить электронные письма в эту категорию, я использую контроллер, обернутый @RequestMapping
с идентификатором категории (UUID), поэтому все действия контроллера всегда происходят в контексте категории, указанной с помощью пути.
Я использую @ModelAttribute
для предварительной загрузки категории контекста для всей области действия контроллера.
Проблема
Этот подход хорошо работал для листинга и отображения форм. Однако это не удается при отправке формы - после небольшой отладки я обнаружил, что данные формы переопределяют параметр моей категории @ModelAttribute
.
В моем коде в методе save()
category
на самом деле не является атрибутом модели, загруженным с помощью метода addCategory()
, но заполняется данными формы (модель email
также заполняется, и это правильно).
Я ищу решение, которое позволит мне привязать данные формы только к определенному @ModelAttribute
.
Я читал в документации Spring MVC, что порядок аргументов имеет значение, но я упорядочил их в соответствии с примерами, и все же это не работает, как ожидалось.
Код
Вот мой контроллер:
@Controller
@RequestMapping("/emails/{categoryId}")
public class EmailsController
{
@ModelAttribute("category")
public Category addCategory(@PathVariable UUID categoryId)
{
return this.categoryService.getCategory(categoryId);
}
@InitBinder
public void initBinder(WebDataBinder binder)
{
binder.registerCustomEditor(Set.class, "categories", new CategoriesSetEditor(this.categoryService));
}
@RequestMapping(value = "/create", method = RequestMethod.GET)
public String createForm(@ModelAttribute Category category, Model model)
{
// here everything works, as there is just a single @ModelAttribute
return "emails/form";
}
@RequestMapping(value = "/save", method = RequestMethod.POST)
public String save(
@ModelAttribute @Valid Email email,
BindingResult result,
Model model,
@ModelAttribute("category") Category category
) {
// saving entity, etc
// HERE! problem is, that response is bound BOTH to `email' and `category' model attributes
// and overrides category loaded in `addCategory()' method
return String.format("redirect:/emails/%s/", category.getId().toString());
}
}
На всякий случай вот еще код формы:
<form:form action="${pageContext.request.contextPath}/emails/${category.id}/save" method="post" modelAttribute="email">
<form:hidden path="id"/>
<fieldset>
<label for="emailName"><spring:message code="email.form.label.Name" text="E-mail address"/>:</label>
<form:input path="name" id="emailName" required="required"/>
<form:errors path="name" cssClass="error"/>
<label for="emailRealName"><spring:message code="email.form.label.RealName" text="Recipient display name"/>:</label>
<form:input path="realName" id="emailRealName"/>
<form:errors path="realName" cssClass="error"/>
<label for="emailIsActive"><spring:message code="email.form.label.IsActive" text="Activation status"/>:</label>
<form:checkbox path="active" id="emailIsActive"/>
<form:errors path="active" cssClass="error"/>
<form:checkboxes path="categories" element="div" items="${categories}" itemValue="id" itemLabel="name"/>
<form:errors path="categories" cssClass="error"/>
<button type="submit"><spring:message code="_common.form.Submit" text="Save"/></button>
</fieldset>
</form:form>
Примечание. Я не хочу, чтобы несколько @ModelAttribute
пришли из POST, просто хочу каким-то образом отличить модель формы от ранее сгенерированных атрибутов.