0 Replies Latest reply on Nov 25, 2008 4:06 PM by Daan Gerits

    Seam, Spring, DAO's and DataModels

    Daan Gerits Newbie

      Hello All,


      I have some issues using Seams DataModel and DataModelSelection with POJO's. When I select an item from my selectOneMenu, bound to a DataModel and attached to a DataModelSelection, The first item is selected from the result list. Now I've read an enormous amount of topics which try to (and sometimes do) find an answer, but none of them seemed to work for me. I'm quite stuck with this one. I could just replace the DataModelSelection with an In(required=false), and change the datatype, but this does not seem to be the way imho.


      Well first let me describe the situation I'm in.


      First of all, we are not using Hibernate, EJB3 or JPA. We pass all persistence issues to a set of Data Access Object (actually dynamic proxies) calling IBatis statements. Now I don't know how much of this is relevant to my problem but i suspect it has an influence on <s:convertEntity/>? Anyway, since I'm not using Hibernate or JPA, I have no Annotations on my POJOs coming from the DAOs.


      Well, my task is to write a search page, using a selectOneMenu to select a family. These families are retrieved from the DAO's:


      My SearchPage, productList.xhtml


      <rich:panel >
        <f:facet name="header">Search</f:facet>
        <h:form>
          <h:outputLabel value="Description:" for="tbDescription" />
          <h:inputText id="tbDescription" value="#{productAction.description}" />
      
          <h:outputLabel value="Family:" for="ddlFamilies" />
          <h:selectOneMenu id="ddlFamilies" value="#{selectedFamily}" >
            <s:selectItems value="#{families}" noSelectionLabel="Please Select..." />
          </h:selectOneMenu>
      
          <h:commandButton id="btFindProducts" value="Find" action="#{productAction.search}" />
        </h:form>
      </rich:panel>



      The Family POJO. Only this type of object is used in the list. See ... No Annotations :)


      public class Family implements BusinessObject {
        private Integer id;
        private String code;
        private String description;
        private Integer language;
      
        /** Getters, Setters, Equals and HashCode */
      }



      The Provider, Responsible for retrieving data from the service. The service is Spring based and contains information on how to contact the DAOs.


      @Name("familyProvider")
      @Scope(ScopeType.CONVERSATION)
      @AutoCreate
      public class FamilyProvider {
        @In("#{familyService}")
        protected FamilyService familyService;
           
        @DataModel(scope=ScopeType.PAGE)
        public List<Family> families;
           
        public Family selectedFamily;
           
      // -- Lookup ------------------------------------------------------------------
           
        @Factory(value="families", autoCreate=true)
        public void lookupAllFamilies() {
          families = familyService.findAllFamilies(1);
        }
           
      // -- Properties --------------------------------------------------------------
           
        @Out(required=false)
        public Family getSelectedFamily() { return selectedFamily; }
           
        @DataModelSelection("families")
        public void setSelectedFamily(Family selectedFamily) {
          this.selectedFamily = selectedFamily;
        }
      }



      Now for the action class, which is the coordinator of all communication, I've create the following:


      @Name("productAction")
      @Scope(ScopeType.SESSION)
      @AutoCreate
      public class ProductAction implements Serializable {
        @In protected ProductProvider productProvider;
        @In protected BrandProvider brandProvider;
        @In protected FamilyProvider familyProvider;
           
        @Logger protected Log log;
           
        protected String description;
           
        @DataModel()
        protected List<SimpleProduct> products;
           
        @DataModelSelection("products")
        @Out(required=false)
        protected SimpleProduct selectedProduct;
           
      // -- Methods -----------------------------------------------------------------
           
        public String view() {
          return "/product.xhtml";
        }
           
        public void search() {
          productProvider.lookupProducts(
                getDescriptionPattern(), 
                familyProvider.getSelectedFamily(), 
                brandProvider.getSelectedBrand()
          );
        }
           
      // -- Properties --------------------------------------------------------------
           
        public String getDescription() { return description; }
        public void setDescription(String description) {
          this.description = description;
        }
           
        public String getDescriptionPattern() {
          if (description == null || description.length() == 0) return "%";
          else return '%' + description.toUpperCase().replace('*', '%') + '%';
        }
      }



      As you can see, the datamodel inside the familyProvider has a page scope. (got this from Seam In Action ... ) and the getters and setters are present, except for the outjected fields of the Action. I tried moving some annotations from their field to a method to allow easy debugging, but nothing changed doing so.


      Is the dataModelSelection retrieving the value from the DataModel internal structure, or is some data access needed to retrieve the actual selected value?


      I suppose convertEntity can only be used with a persistanceManager, so using it is out of the question for me. Are there any other options, is it even needed?


      I broke my head on this for quite some time now but I don't see an error. Maybe it's just me ...