Announcement Announcement Module
Collapse
No announcement yet.
Domain Objects and forms Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Domain Objects and forms

    Hi,
    I am trying to use spring mvc annotated controllers, I have two domain entities that have a ManyToMany relationship. How do you handle form data that has one entity in a collection<Address> addresses; how do I bind to the properties in the class in the colleciton? Would be grateful for any guidence on this matter.
    Thank you...

  • #2
    registeCustomEditor() might be problem

    Its also not working for me.

    I have the following problem:

    i have been looking at so many posts regarding this, but haven't got any working sample.
    I have also looked at all those selecting check box problem and stuff.
    My domain object are as follows
    Code:
    public class User {
      String userName;
      Set<UserRole> roles;
    ... all setters and getters..
    }
    
    public class UserRole {
      int id;
      String roleName;
    ...all setters and getters..

    I have this in my jsp:
    Code:
    <form:form modelAttribute="user">
    <form:select path="roles">
    	<form:options items="${user.roles}" itemValue="roleName"
    		itemLabel="roleName" />
    	</form:select>
    </form>
    I set the model attribute "user" in the GET request handler in the controller.
    I have other javascript code also to modify the contents of the SELECT element to add/remove options. (javascript side is working as I have debugged and seen the servlet request about the actual contents coming from the SELECT element).

    On display, it is displaying properly. i.e. if all roles of the user can be seen in the SELECT element.

    But when i submit the form, I am not able to get the user with the modified roles.
    My controller handler has something like:
    Code:
    @RequestMapping(method = RequestMethod.POST)
      public ModelAndView processSubmit(final HttpServletRequest request, @ModelAttribute("user") final User user) {
    //store the updated user... etc
    }
    I registered a custom editor for the UserRole class but its not working
    Code:
    @InitBinder
      public void initBinder(final ServletRequestDataBinder binder) {
         binder.registerCustomEditor(Set.class, "roles", new CustomCollectionEditor(HashSet.class) {
          @Override
          protected Object convertElement(Object element) {
            Object obj = super.convertElement(element);
            if (obj instanceof String) {
              return userRoleDao.findByRoleName((String) obj);
            }
            return null;
          }
    });
    I have debug points in the convertElement(), but whenever I submit the form it never comes there. And the user instance that I receive in the POST handler in the controller does not contain the modified roles.

    What am i missing here when registerring the property editor ???

    Comment


    • #3
      I think you should not be calling the super method, because the super class would not know how to convert the submitted element to the target type.
      Code:
      @InitBinder
        public void initBinder(final ServletRequestDataBinder binder) {
           binder.registerCustomEditor(Set.class, "roles", new CustomCollectionEditor([HashSet.class) {
            @Override
            protected Object convertElement(Object element) {
              // comment this line Object obj = super.convertElement(element);
              if (obj instanceof String) {
                return userRoleDao.findByRoleName((String) obj);
              }
              return null;
            }
      });
      Last edited by maverickthinker; Aug 8th, 2008, 07:14 PM. Reason: correction

      Comment


      • #4
        I tried commenting the line as u told, but still its not working.

        The line where i register the editor should be
        Code:
        binder.registerCustomEditor(Set.class, "roles", new CustomCollectionEditor(Set.class) {
        ...
        Still when I do a submit, it never comes to the convertElement() method. It comes upto the point where I register the editor, but the editor is never called.

        This was supposed to be a simple stuff. Its not working... am losing my hair on this. Its been two days now.

        I have tried so many combinations of binder.registerCustomEditor(...), none seem to work. Please help... its just a matter of binding objects from the request, in normal servlet programming, i would have done this in 2 mins.

        Just wanted to use the "framework".

        Comment


        • #5
          Can you post the error message that you are getting?

          Comment


          • #6
            I am not getting any errors as such. The user object that i get in the post handler in the controller does not have the new values of roles that I change from the browser (using javascript). And i am sure the roles are getting changed, as I did request.getParameterValues("roles") and I can see the new list of roles.

            The custom editor is not called in POST. I can see that it comes in the initBinder method and register the custom editor, but the convertElement is never invoked in the POST. Again surprising thing is that the convertElement in the custom editor gets invoked in GET.

            It directly comes in my controller POST handler with the @ModelAttribute user and this user does not contain the modified roles from the browser but contains whatever roles that were assigned while giving the user back in GET.

            I am wondering if I am doing the right thing with the form:select in the jsp (though its so trivial, I am hoping nothing is wrong). Why is the form data not getting bound the user role even after I have added the custom collection editor??

            Comment


            • #7
              Did not pay attention to the jsp tag. Since you are using a select tag the roles property will always have only one value selected right? So why a Set in the domain object.

              If you are using that to display the available options, then you should be using referenceData method to populate a seperate model attribute.

              Code:
              <form:select path="country">
                            <form:option value="-" label="--Please Select"/>
                            <form:options items="${countryList}" itemValue="code" itemLabel="name"/>
              </form:select>
              In the above example from the spring documentation countryList is a model attribute populated via the referenceData method. Where as notice the property country i.e being bound to. This can just be a plain property in the domain object.

              Now if it were a multi-select then i.e. a whole another issue.

              Hope re-designing the domain object & select field helps.

              Comment


              • #8
                Yes... the select field has multiple selects. I pasted the wrong code in my first post..
                Here's a snippet of the jsp:
                Code:
                <form:select path="roles" cssClass="option" multiple="multiple">
                								<form:options items="${user.roles}" itemValue="roleName" itemLabel="roleName" />
                							</form:select>
                And here's the generated html:
                Code:
                <select id="roles" name="roles" class="option" multiple="multiple">
                								<option value="NORMAL" selected="selected">NORMAL</option><option value="SUPER_USER" selected="selected">SUPER_USER</option>
                							</select><input type="hidden" name="_roles" value="1"/>

                The roles are still not getting bound. I believe the main problem is the custom editors -- the call is just not going through the convertElement() in the POST submit.

                Comment


                • #9
                  Just wanted to mention that the user is also a SessionAttribute.

                  When I do a request.getParameterValues("roles") ad print it, in the initBinder method and also the POST handler, I get the values submitted from the browser.


                  Why isn't spring binding the values to the roles property in the User domain???
                  Please help.

                  Comment


                  • #10
                    Better explanation

                    Hi all,
                    My situation is a bit different I'm not trying to fill a List in the view sorry if my explantion was a bit vauge. I have twoEntity classes which have a oneTomany relation ship i.e Account can have many addresses, which I have in the account code:
                    @Entity
                    public class Account {
                    private long id;
                    private String userName;
                    private String password;
                    private Collection<Address> addresses;

                    // Getters/Setters
                    }

                    now in the formcontroller how would I go about creating the Address object and adding it to the collection? The userName and password properties are fine, I understand this bit but to add an address to the collection has got me stumped....

                    Comment


                    • #11
                      Chainy

                      At what point do you want to create the address object?

                      Comment


                      • #12
                        abhi.sanoujam

                        I give up. I think this issue needs a fresh set of eyes.

                        Comment


                        • #13
                          I think i am also giving up

                          I'll just create my roles in the POST handler. Its so easy there with something like the following:

                          Code:
                          @RequestMapping(method = RequestMethod.POST)
                            public ModelAndView processSubmit(final HttpServletRequest request, @ModelAttribute("user") final User user,
                                                              final BindingResult result, final SessionStatus status) {
                              String [] newRolesStr = request.getParameterValues("roles");
                              Set<UserRole> newRoles = new HashSet();
                              for (String role : newRolesStr) {
                                newRoles.add(userRoleDao.findByRoleName(role));
                              }
                              user.setRoles(newRoles);

                          Please, spring experts out there, if you can help, please tell me a way how I can bind these roles using the WebDataBinder, without actually doing it manually. I guess this is a pretty basic stuff and I am sure ppl must have been able to do it.

                          mavericthinker: thanks for taking interest and looking into the matter

                          Comment

                          Working...
                          X