views:

26

answers:

2

The Spring MVC binding mechanism is powerful, but I'm now confronted with a trivial issue that I wonder how to resolve:

  • User JPA entity, that is used for the binding and validation as well (i.e. throughout all layers)
  • "Edit profile" page, that is not supposed to change the password or some other entity properties

Two ways that I can think of:

  1. Using the same object

    • use @InitBinder to configure a list of disallowed properties
    • obtain the target user (by id)
    • then use a reflection utility (BeanUtils) to copy the submitted object to the target object, but ignore null values - i.e. fields that are not submitted
  2. Introduce a new object that has the needed subset of fields, and use BeanUtils.copyProperties(..) to merge it to the entity.

Alternatives?

A: 

Hi Bozho,

I just checked up with two of the last Spring projects I have worked on and in both places the following approach is taken:

In the JSP page for the form the change password field has a name that does not match the name of the password field in the User bean, so that it doesn't get mapped to the bean. Then in the onSubmit method there is a separate check whether a new password has been submitted, and if it has been, the change is reflected explicitly.

Поздрави, Vassil

vstoyanov
thanks, the password-change will be handled by a simple `request.gatPerameter(..)`, but there are many more properties of the `User`, that are not to be submitted / bound.
Bozho
Well, in that case I think you have two choices:1. Have all the properties' values output in the form (maybe using hidden fields for some).2. Use an InitBinder - after all that's what they are meant for.
vstoyanov
+1  A: 

I've found that as soon as your web model starts to diverge from your business layer in function, it's best to use a view layer object (a model object) to collect, or display the data

the entity:

public class com.myapp.domain.UserEntity {

}

the model object:

public class com.myapp.somesite.web.SomeSiteUserModel {

   public static SomeSiteUserModel from(UserEntity userEntity) {
      ... initialize model ...
   }

   public UserEntity getModelObject() {
      ... get entity back ... 
   }

}

now all view based operations can hand off processing to the internal model object if that makes sense, otherwise it can customize them itself. Of course the problem with this is you have to re-write all the getters and setters you want for the entity (an issue that I've had to deal with, that is annoying) unfortunately that is a bit of a Java language issue

walnutmon
I ended up implementing it that way, just with a note that for "initialize model" I used `BeanUtils.copyProperties(..)`
Bozho
very nice, I've had a need for something like that before, but had always ended up just doing it manually, thanks!
walnutmon