So I’ve got a simple form through which I can either “add” a new Thing, or “update” an existing Thing.
What I would like is to have one controller that can process both adding and updating. On the outset this seems simple enough, until I consider the problem of using setDisallowedFields in my InitBinder so that the “id” field is not allowed when adding a new Thing.
Currently I have two controllers with what could be identical code except for the InitBinder method.
Any suggestions or advice? (I’m open to the argument that I should want to maintain two controllers also, if you can give me good reasons)
Actually, you should disallow the “id” field both when adding AND updating. Otherwise a malicious user could tamper with the value of the “id” request parameter of an update request and thereby update a different record to the one shown by the form (assuming there’s no ACLs or other domain-level security).
However if you simply disallow the “id” field, the controller will treat the ID as being null, which will work when inserting but not when updating (e.g. it might try to insert a new record instead of updating, depending on what persistence mechanism you’re using). So you want the controller to remember the non-editable values of your domain object (not just IDs, but all disallowed fields) between requests so that it can send all the correct values to the service layer or other business logic. This is done using the type-level @SessionAttributes annotation, as follows (other annotations omitted for clarity):
For even better security, set the allowed fields rather than the disallowed fields. Either way you need the @SessionAttributes annotation to fill in whatever existing field values are ignored from the request.