Announcement Announcement Module
Collapse
No announcement yet.
Seeking advice on collections in commands and persisting them Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Seeking advice on collections in commands and persisting them

    I'm starting to refactor my app after its 1.0 release. One thing I'm trying to do is simplify and cut down on code. When I started the project, it was initially done using Struts, but about a quarter of the way through, I switched to Spring. However, there were artifacts that still persisted for a while, namely, the notion of a Struts form bean that's decoupled from the db entity.

    About half way through my project, I started doing more domain driven development cuz it seemed faster and simpler to code. So I have a question regarding how people implement domain objects straight in forms and persist them straight back to the db. When the user clicks 'submit' the goal is to validate, check some biz logic if necessary, and then persist. I'm using Spring 1.2.5 and Hibernate 2.1.7. I have a simple case: User submits a news article that has multiple categories. The model looks like so:

    Code:
    package content;
    public class News {
       private Long id;
       private String title;
       private String description;
       private Set categories;
    
       // gets/sets go here
    }
    
    ----
    
    package content;
    public class Category {
       private Long id;
       private String name;
       private Long typeId;
       // gets/sets here
    }
    In my Hibernate news.hbm.xml file I have the following relationship defined for the categories:

    Code:
        <set name="categories" lazy="false">
          <cache usage="read-write"/>      
          <key column="content_id"/>
          <one-to-many class="content.Category"/>
        </set>
    All the above works fine. However, I have two issues that relate to each other.

    First on the view side, I'm not sure how I would model the categories in the news object. Currently my controller provides a Set of all the categories available and make them avail to the view (which is a JSP using JSTL). The the controller also provides this command object for the view form:

    Code:
    public class EditNewCommand {
        private News news;
        private Long[] categoryIds
        // gets/sets here
    }
    The view then iterates over all the categories that the controller dropped in the request scope as a separate attribute. The view then iterates over the Set of master categories and then over the category Set that's in my News object. If there's a match in the news categories to the current master category, the view marks that as selected in my multi-select box - typical behavior I'm sure. Everything at this point renders fine to the user.

    User submits and the controller auto-populates my command fine. However, since I don't really see a way to persist the News object in its entirety - due to the Set not being able to completely render in the view - I have to use a command that contains the News object, but also needs to have its own way to track the category ids - separately from the News object itself. Hopefully this makes sense as when it comes down to it, I can 'serialize' for the most part, a News object back and forth from a form via the text fields fine. But, I cannot 'serialize' a Content object, which is contained in a Set, into on select list option tag.

    I can, however, use the Category id and name in a opton tag and this is what I use the categoryIds for on the command object; to hold the ids the user has selected from the select tag.

    The second issue, which is related to the first, is when my News object is sent back to my Dao, I need to also pass the contentIds. The Dao then deletes all the current Content objects related to the current News object. It then looks up a new Set (or List) of Content objects based on the categoryIds array passed in. From there I can then assign that Set of categories to the News object and finally save it.

    What would be ideal is this:

    1. Not having to have a separate contentIds array to track the Content selections a user has chosen - these can be the same or with additions or subtractions.

    2. Just be able to save the News object and not worry about looking up a new Set of Content objects based on the contentIds array passed in. I know Hibernate can cascade everything, but I can't see how it knows what categories have been chosen and therefore what to persist. If I did just do save or update, would Hibernate then fetch all the Category objects based off the ids selected in a a drop down and then automagically hook everything up?

    These are questions and specifics I have, hopefully it's not too confusing. I know I first started this project using 'old school' techniques. I'm really into slimming down everything to try to make it faster, use less code, and speed up my development time. So the above example is just one thing for me.

    Any suggestions / comments / questions would be greatly appreciated.

    Thanks!

  • #2
    Checkout http://forum.springframework.org/sho...ght=checkboxes

    that will answer *some* of your questions.

    Comment


    • #3
      Thanks

      I think this starts me in the right direction. Wasn't really thinking of property editors when I probably should have.

      Comment


      • #4
        Originally posted by jlee

        The model looks like so:

        Code:
        package content;
        public class News {
           private Long id;
           private String title;
           private String description;
           private Set categories;
        
           // gets/sets go here
        }
        
        ----
        
        package content;
        public class Category {
           private Long id;
           private String name;
           private Long typeId;
           // gets/sets here
        }


        .... The view then iterates over the Set of master categories and then over the category Set that's in my News object. If there's a match in the news categories to the current master category, the view marks that as selected in my multi-select box - typical behavior I'm sure. Everything at this point renders fine to the user.

        How i can do that? i can't bind multiple values of multi-select box to mi object. That's is making me crazy!

        Comment


        • #5
          Originally posted by dcasanueva
          How i can do that? i can't bind multiple values of multi-select box to mi object. That's is making me crazy!
          Actually I got all this working by extending a Spring CustomCollectionEditor. In my object, Spring calls the overridden setValue method and then passes me in a String[] that has all the multiple select box values that a user has selected. I think go thru those, look up my category objects based on those ids, and then set a local var called theSet, which is just Set object. Then when Spring calls the getValue method, my object returns the correct Set of Category objects and the binder sets my command correctly. Pretty slick.

          Comment


          • #6
            thax jlee for your reply, but not works for me :S

            look at this,

            http://forum.springframework.org/showthread.php?t=19808
            this is my problem,

            it's my propertyEditor badformed?

            Comment


            • #7
              Originally posted by dcasanueva
              thax jlee for your reply, but not works for me :S

              look at this,

              http://forum.springframework.org/showthread.php?t=19808
              this is my problem,

              it's my propertyEditor badformed?
              I think I might see why. If your SELECT box is multiple, then the property editor setAsText will not be called as the setValue method is the one that can accept a String[], which is what is passed on a multiple SELECT. I have something similar in my property editor.

              Code:
              public class ContentCategories extends CustomCollectionEditor {
              
              Set theSet;
              
                  public void setValue( Object object ){
                      String[] strings = (String[])object;
                      List categories = new ArrayList();
                      for( int i=0; i<strings.length; i++ ){
                          try {
                              Long id = Long.valueOf( strings[i] );
                              categories.add( id );
                          }catch( NumberFormatException ne ){}
                      }
                      theSet = categoryService.getAllCategories( categories );
                  }
              
                  public Object getValue(){
                      return theSet;
                  }
              }
              For me this works as my class. Maybe it'll help.

              Comment


              • #8
                Thanks jlee for your help! I found that the view is retrieving a Set instead of a string[], but this set is empty :S , i don't know what is happening.... 3 days with a problem like this, i'm crazy!

                Any idea? i post my jsp page in http://forum.springframework.org/showthread.php?t=19808

                Comment

                Working...
                X