Results 1 to 5 of 5

Thread: Turning off parameter mapping in read-only HTTP requests

  1. #1
    Join Date
    Oct 2012
    Posts
    3

    Default Turning off parameter mapping in read-only HTTP requests

    Hi,

    I'm starting to play around with SpringMVC and I was trying to figure out what would be the best approach to link my entities to the web views as stateless as possible.

    One way I've found is to use the @ModelAttribute on a method that receive in parameter (from the request) the entity ID, which finds it from the service/persistence layer, and return it so it is inserted into the Model of the current request.

    In addition, Spring MVC binds any incoming parameter that matches a field of my entity and updates its value automatically (through the WebDataBinder object).

    My question is concerning this last behaviour. I find it useful that my entity gets updated when some data has been posted by the client. But I would like to avoid it on a simple GET request (which I see as read-only). Current behaviour would allow to update the entity by adding parameter in the query of such request, which could be a security issue.

    I know about the dataBinder.setAllowedFields() and stuff but I would prefer a way to disable any kind of field mapping a any GET request. Is there any way to do it?

    Here's a sample prototype to make it clearer what I am looking for...

    Code:
        @ModelAttribute Entity retrieveEntity(@RequestParam(required=true) Long id) {
        	// This is called before the request handler and before parameters are mapped to the entity
        	return entityRepository.get(id);
        }
        
        @RequestMapping(value="/modify", method=RequestMethod.POST) 
        public ModelAndView handleModifyRequest(@ModelAttribute Entity entity) {
        	// Here, I want my entity to reflect the parameters passed in the posted form (this works)
        	....
        }
        
        @RequestMapping(value="/read", method=RequestMethod.GET) 
        public ModelAndView handleReadRequest(@ModelAttribute Entity entity) {
        	// Here, I DON'T want my entity to reflect the parameters passed in the URL (which is what happens...)
        	....
        }
    Thanks!

  2. #2
    Join Date
    Jun 2006
    Location
    The Netherlands
    Posts
    13,625

    Default

    You already mentioned your solution, use InitBinder... If you read the documentation you will notice you can use (almost) the same method arguments in the initbinder method as in normal request handling method. Simply detect the GET request and disable binding (by disallowing all fields for instance).
    Marten Deinum
    Java Consultant / Pragmatist / Open Source Enthousiast / Author


    Pro Spring MVC: With Web Flow
    Conspect

    Have you read the reference guide.
    Use the [ code ] tags, young padawan

  3. #3
    Join Date
    Oct 2012
    Posts
    3

    Default

    Quote Originally Posted by Marten Deinum View Post
    You already mentioned your solution, use InitBinder... If you read the documentation you will notice you can use (almost) the same method arguments in the initbinder method as in normal request handling method. Simply detect the GET request and disable binding (by disallowing all fields for instance).
    Yes, but I was wondering if it was possible to disable the binding other than field by field, which is not really efficient for maintenance (if you modify the entity, you have to remember to adjust the field strings properly in one or more controllers...). Kind of "binder.skip()" thing. Seems not.

    Finally, I decided to go with something like this, since it seems that the parameter mapping happen only if the request handler method takes a ModelAttribute parameter

    Code:
    @ModelAttribute Entity retrieveEntity(@RequestParam(required=true) Long id) {
        return entityRepository.get(id);
    }
    
    @RequestMapping(value="/modify", method=RequestMethod.POST) 
    public ModelAndView handleModifyRequest(@ModelAttribute Entity entity) {
        // Here, the request parameters have been mapped to the entity
        ....
    }
    
    @RequestMapping(value="/read", method=RequestMethod.GET) 
    public ModelAndView handleReadRequest(ModelMap model) {
        // This will avoid any parameter mapping to the entity
        Entity entity = (Entity)model.get("entity");
        ....
    }
    Any better solution is welcome! Thanks,
    Baril

  4. #4
    Join Date
    Jun 2006
    Location
    The Netherlands
    Posts
    13,625

    Default

    I strongly suggest a read of the documentation of the DataBinder... You don't have to specify fieldnames, it can also take a wildcard.. So something like this would work..


    Code:
    if (request.getMethod().equals("GET") {
      binder.setDisallowedFields("*"); // Dissallow binding
    }
    Marten Deinum
    Java Consultant / Pragmatist / Open Source Enthousiast / Author


    Pro Spring MVC: With Web Flow
    Conspect

    Have you read the reference guide.
    Use the [ code ] tags, young padawan

  5. #5
    Join Date
    Oct 2012
    Posts
    3

    Default

    Exactly what I was looking for! Tested and works, thanks!

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •