Results 1 to 7 of 7

Thread: Clearing Fields

  1. #1
    Join Date
    Mar 2011
    Posts
    7

    Default Clearing Fields

    I have a domain object which I am presenting on a typical form. Here is a simplified example:

    Code:
    public class Name implements Keyed {
    
        private String firstName;
        private String middleName;
        private String lastName;
        private Number key;
    
        //Getters and Setters
    }
    Let's say I have two type of users whom can each modify these Name objects. For some silly reason one group is not allowed to see / edit the middle names of the users. So I leave that field off of the form (no hidden field either).

    Is there anyway to keep Spring from clearing that middle name field (i.e it wasn't displayed to the user, hence it couldn't have changed)?

    I could create a new object for this, but it seems like duplication which shouldn't be needed.

  2. #2
    Join Date
    Jan 2011
    Location
    Kirovohrad, Ukraine
    Posts
    59

    Default

    Could you show your controller update method please? Also form markup could be helpful.

  3. #3
    Join Date
    Mar 2011
    Posts
    7

    Default

    Controller Code:
    Code:
        @RequestMapping()
        public ModelAndView nameModification(@ModelAttribute("name") Name name, BindingResult result) {
            
            ModelAndView mav = new ModelAndView("pages/editName");
    
            if (name == null || name.isEmpty()) {
                name = nameDao.getValue(1); // Hard coding just for ex
            }
    
            logger.debug(name.toString());  
            mav.addObject("name", name);       
            return mav;
            
        }
    We are using velocity, so below is the code

    Code:
    <form target="_self" enctype="application/x-www-form-urlencoded" action="changeName.vm" method="post">
    
        <span>Full Name</span>
        #springBind("name.first")
        <label for="name.first">First Name: </label>
        #springFormInput("name.first", "")
     
        #springBind("name.last")
         <label for="name.last">Last Name: </label>
         #springFormInput("name.last", "")
    
    </form>
    So on the get, let's say our dao returns the following name:

    Samuel Langhorne Clemens

    Upon posting (for someone whom can only see first and last names), say the user inputs Mark Twain.

    The name is now Mark Twain --> Langhorne is now gone.

  4. #4
    Join Date
    Jan 2011
    Location
    Kirovohrad, Ukraine
    Posts
    59

    Default

    Ok, now I understand your problem.

    In fact that is by design. The name instance that is passed to controller method is created from the request parameters, the process is called binding. So if your form doesn't contain middle field it has no way to appear in the name parameter passed to controller. The key point here is that it has nothing to do with your DAO.

    Let's have a good look at your particular example. Pretend you have a Name stored in the DB with id = 1, name = Samuel, middle = Langhorne and last = Clemens. Let's also pretend that you have two user roles: ROLE_A can change name and middle, ROLE_B can change name and last.

    First this to do is to display relevant fields for the form depending on user role:
    HTML Code:
    <form target="_self" enctype="application/x-www-form-urlencoded" action="changeName.vm" method="post">
        <span>Full Name</span>
        #springBind("name.first")
        <label for="name.first">First Name: </label>
        #springFormInput("name.first", "")
    
        #if($security.AllGranted("ROLE_A"))
        #springBind("name.middle")
        <label for="name.middle">Middle Name: </label>
        #springFormInput("name.middle", "")
        #end
    
        #if($security.AllGranted("ROLE_B"))
        #springBind("name.last")
        <label for="name.last">Last Name: </label>
        #springFormInput("name.last", "")
        #end
    </form>
    See these posts for how to get $security available in your templates. Note, I haven't tried it myself, but it should work .

    Now you need to obtain the Name stored in the DB using the submitted id (1), update properties allowed depending on roles current user is (2) (since nothing prevents him from POSTing fields not shown in markup, never trust the user ) and then save it back to the db (3).
    Code:
    @RequestMapping
    public ModelAndView nameModification(Name name, BindingResult result) {
        Name originalName = nameDao.getById(name.getId()); // (1)
        
        // TODO: Handle missing DB entry somehow
    
        boolean hasRoleA = false;
        boolean hasRoleB = false;
        for (GrantedAuthority authority : SecurityContextHolder.getContext().getAuthentication().getAuthorities()) { // (2)
            if (authority.getAuthority().equals("ROLE_A")) {
                hasRoleA = true;
            } else if (authority.getAuthority().equals("ROLE_A")) {
                hasRoleB = true;
            }
        }
        
        originalName.setName(name.getName());
        if (hasRoleA) { // (2)
            originalName.setMiddle(name.getMiddle());
        }
        if (hasRoleB) { // (2)
            originalName.setLast(name.getLast());
        }
    
        nameDao.save(originalName); // (3)
        
        ModelAndView mav = new ModelAndView("pages/editName");
    
        logger.debug(originalName.toString());  
        mav.addObject("name", originalName);       
        return mav;
    }

  5. #5
    Join Date
    Mar 2011
    Posts
    7

    Default

    That's a pretty painful process on our DB!

    We first must lookup the user (if one exists on the initial search page), then redirect them to this new page, where we must again pull them from the DB to ensure freshness.

    Then upon posting, we have to pull them from the DB to persist the middle name?

    That's 3 hits for lookup, plus another one to save the user (if changes occur).
    Not to mention the fact that we'd then have to implement our security code to utilize spring security as well (although I'd see this as a win, I'm not so sure others on the team would).

  6. #6
    Join Date
    Jan 2011
    Location
    Kirovohrad, Ukraine
    Posts
    59

    Default

    Quote Originally Posted by sgentry View Post
    That's a pretty painful process on our DB!
    Oh, please don't blame me That's your business requirements. But I doubt it is a huge DB hit. How often is this name change used in your system? Is it at least 10% of use cases? Also note that fetching a row by primary key (that's what we are doing in this code) is extremely optimized in all DBMS I've heard of.

    Quote Originally Posted by sgentry
    We first must lookup the user (if one exists on the initial search page), then redirect them to this new page, where we must again pull them from the DB to ensure freshness.
    I wasn't aware of these two steps performed before Name update since you didn't mention them, but I don't think there's another option here.

    Quote Originally Posted by sgentry
    Then upon posting, we have to pull them from the DB to persist the middle name?

    That's 3 hits for lookup, plus another one to save the user (if changes occur).
    In fact you may omit this fetch. Implement two extra methods updateNameAndLast(Name name) and updateNameAndMiddle(Name name). Depending on underlying technology used you'll need to create a custom SQL/HQL/JPQL update query for each of them.

    Quote Originally Posted by sgentry
    Not to mention the fact that we'd then have to implement our security code to utilize spring security as well (although I'd see this as a win, I'm not so sure others on the team would).
    Well, Spring Security is not a must. I just thought you are already using it since you mentioned two type of users in your initial post. Just substitute the view and controller logic based on Spring Security with the one you already use, I just showed the concept.

  7. #7
    Join Date
    Mar 2011
    Posts
    7

    Default

    Haha, no blame intended to be implied.

    While you're correct on the part of lookup on primary key, we have other instances where we are dealing with many many results. Looking up by that type of query is expensive. We're also likely to experience large user growth, so any extra performance I can squeeze out of the DB will be greatly appreciated.

    I hadn't mentioned the PRG pattern, but that is how these pages are being dealt with.

    Thanks for your example.

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
  •