views:

967

answers:

4

I am using Spring MVC and in my controller, I want to be able to automatically bind incoming parameters to my Java object. It seems like this should be pretty easy to do. The only wrinkle is that the incoming parameter names (e.g. "username") may not match up exactly with the field name in the java object (e.g. "name").

From the Spring documentation (http://static.springsource.org/spring/docs/2.5.6/reference/mvc.html):

"Spring Web MVC allows you to use any object as a command or form object.... All this means that you don't need to duplicate your business objects' properties as simple, untyped strings in your form objects just to be able to handle invalid submissions, or to convert the Strings properly. Instead, it is often preferable to bind directly to your business objects. "

How do I actually do this? Any code or links appreciated.

For example, my business object

public class User {
  private String username;
  private String password;

  //getters and setter
}

The request my controller is handling:

example.com/login?name=Steve&pw=1234

I would like to bind "Steve" to User.username and "1234" to User.password.

Thanks.

A: 

example.com/login?username=Steven&password=1234

You can't expect spring MVC to do automatic binding when the property names don't match up. That's just not logical.

Thanks for the reply.Hmm, then it seems like the quote from SpringSource I pasted in my question is sort of false advertising.It is also not logical to have the field names in your java object coupled so tightly to the parameter names in an html form, for example. If you refactored your java class and renamed fields, your controllers would stop working!
I'd rather have my model bound to my view than have my view bound to my controller, which would be the case if you map "name" to "username" within the controller.
JacobM
A: 

EDIT: Do what Kaleb said, overriding formBackingObject is cleaner.

I'll leave this note though:

However, if you have any control over both sides, I strongly recommend making the name consistent. Convention over configuration.

bpapa
thanks for the reply. although it seems like often you would want the field names in your business logic to not be the exact same ones you expose."accountAdminContactFirstName" might not be a great name to see in an URL. "name" might be cleaner.
In my mind that shouldn't be in the URL anyway. Either do a POST or rewrite the URL to not have parameters in it.
bpapa
Actually, `account.adminContact.firstName` would be cleaner :-) And it's supported by Spring, too. `bpapa` is completely right - you will make your life **a lot** easier by having consistent naming scheme
ChssPly76
Ok yes, that was a contrived example.My use case here is exposing an API call, for example: a POST to example.com/api/user with name and password key/values in the bodyonce this is exposed and the api is used by others that means I can never rename the corresponding fields in my User java object! that coupling doesn't make sense to me.Thanks.
Spring MVC may not be the best approach to API handling; you may want to take a look at restlets or using web services instead. That said, I'm not sure I understand your argument - if your java User object was exposed as part of public API you could never change its fields (or, rather, public methods) either; so why should "web-based" API be any different?
ChssPly76
+1  A: 

If I remember correctly, you can override public Object formBackingObject(HttpServletRequest request) and manually setup your command POJO.

Kaleb Brasee
Word of caution - the above method is only defined for form controller hierarchy - `AbstractFormController` and children. It's not going to work for basic command controllers, where the only way to override parameter names is to implement custom `ServletRequestDataBinder` which is rather involved.
ChssPly76
That's true... I usually use it within a SimpleFormController.
Kaleb Brasee
A: 

If you want to bind request to the POJO you may need to extend AbstractCommandController or if you have a form - SimpleFormController. I believe you will need the servlet version from org.springframework.web.servlet.mvc package.

  • use setCommandClass() to setup the correct type of your backing bean in controller constructor, ie POJO:

    setCommandClass(User.class);

  • formBackingBean() used to create new instance of the POJO, that would be used by controller.

  • controller is responsible for mapping request parameters to the POJO fields.
  • if mapping is not working good for you, than override formBackingBean() or onBind() methods to read request paratemers and put values to POJO.
ruslan