PDA

View Full Version : Domain objects with setters only?


DaveIrving
Oct 12th, 2006, 04:39 AM
I've got a "User" in the domain model which describes a user of my application.
I'd like to not expose the password in the model (with say, "getPassword") - as the User is capable of validating passwords itself (User#passwordMatches(String) ).
However, I'd also like to be able to add new users thru a SpringMVC form - which seems to be requiring me to have a getter for the passwords setter.

I know that in the general case, this makes sense - but is there any easy way to bypass this for a specific field (I couldn't find one..), or could anyone give any hints on what I can hack to make it work?

(At the moment its blowing up in ...servlet.support.BindStatus#getFieldResult which digs in to the BeanWrapper)

Dave

DaveIrving
Oct 12th, 2006, 05:31 AM
Hmmm... Thinking about it, maybe what I should be doing is overidding writeValue in PasswordInputTag...
That ought to do the trick.

DaveIrving
Oct 12th, 2006, 05:36 AM
Darn it - maybe not. Looks like Im going to have to start digging around in AbstractDataBoundFormElementTag :o(

DaveIrving
Oct 12th, 2006, 05:53 AM
And it gets worse... It looks like trying to mess with AbstractDataBoundFormElementTag#getBindStatus() is going to screw-up the whole property binding mechanism.

Is there no way to bind on to a domain object which doesn't have a getter for a field?

geggle
Oct 12th, 2006, 08:49 AM
Maybe I'm missing something but why not just implement a getPassword() method on your command object that returns an empty string (or maybe "****" or something similar?)

Marten Deinum
Oct 12th, 2006, 09:21 AM
Dave spring uses the default javabeans mechanism for getting/setting properties. So it is checking foor get/set/is methods. Anyother way you would implement yourself.

However checking your first post I figure that you are using some sort of Rich Domain Model. So I also guess you have some constructor like


public User(String username, String password, ......)


What you could do, as a work around. Is to create a seperate formBackingObject for the NewUserController. This form would then only contain the properties needed to create a user.

Then in the onSubmit method you would copy those properties to the constructor of the User method.

It's a bit of a workaround but works quite nicely. There was also once a thread going on about an even more fine grained solution, just use the search Luke eh Dave :).

DaveIrving
Oct 12th, 2006, 10:16 AM
Thanks for the replies everyone!

I didn't want to put a "getPassword" in the model - because it just isn't something that really needs to be exposed from the User - and I dont want to do it just to satisfy Spring :)

I've just finished my work around, and it turned out very similar (I think) to what Martin suggested.

What I have is a UserWrapperForm which has an underlying user and also holds the password.
So it has "getUser/setUser" and "getPassword/setPassword".
I can then map on to this from the form which means I get the password available for the UI form - and dont even have to duplicate the other fields - they just get mapped as (for example) path="user.emailAddress".

The other thing I found I could add here was the standard "repeat your password" functionality (as I asterisk the password in the UI). The wrapper has a password and "repeat" password - and an "getPasswordsMatch" method.

I can then use valang to validate that the user provided matching candidate passwords.

So I kinda got the best of both worlds: Added UI specific functionality without having to duplicate fields from the domain model.

Dave