3 Replies Latest reply on May 19, 2010 4:34 PM by Martin Höller

    Field error in seam bean

    Raphaël M. Newbie

      Hi i have a problem to display some components like a simple list in a JSF page.


      The goal of my code is to have a generic list of objects (lazy loaded) to display in different pages with a specific implementation.
      In the implementation i have some bean variables that i need to initialize and move to choose the list i will display.


      The problem is that if i put everything in one bean without any inheritance it works!
      And with the code below i have this error :


      java.lang.NumberFormatException: For input string: "choixCatalogue"
           at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48)
           at java.lang.Integer.parseInt(Integer.java:447)
           at java.lang.Integer.parseInt(Integer.java:497)
           at javax.el.ListELResolver.coerce(ListELResolver.java:166)
           at javax.el.ListELResolver.getValue(ListELResolver.java:51)
           at javax.el.CompositeELResolver.getValue(CompositeELResolver.java:53)
           at com.sun.faces.el.FacesCompositeELResolver.getValue(FacesCompositeELResolver.java:72)
           at org.jboss.el.parser.AstPropertySuffix.getValue(AstPropertySuffix.java:53)
           at org.jboss.el.parser.AstValue.getValue(AstValue.java:67)
           at org.jboss.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:186)
           at org.jboss.seam.core.Expressions$1.getValue(Expressions.java:112)
           at org.jboss.seam.navigation.Param.getStringValueFromModel(Param.java:137)
           at org.jboss.seam.navigation.Pages.getStringValuesFromModel(Pages.java:762)
              ....
      


       
      So the code, the generic list :


      @Scope(ScopeType.CONVERSATION)
      public abstract class LazyList<T> extends AbstractList<T> implements Serializable {
      
           private static final long serialVersionUID = -7605315613035999016L;
           private static final int defaultPageSize = 5;
      
           protected Map<Integer, T> lazyList;
           protected int numberOfResults;
           protected int currentPage;
           protected boolean hasMore;
           protected int pageSize;
      
           @Create
           public void create() {
                lazyList = new HashMap<Integer, T>();
                this.pageSize = defaultPageSize;
                this.numberOfResults = 0;
                this.currentPage = 0;
                this.hasMore = false;
           }
           
           public abstract void getFirstResults();
      
           public abstract T getMoreResults();
      
           public abstract int getCurrentLoadedSize();
      
           public void lazyLoading() {
                if (!lazyList.containsKey(currentPage)) {
                     T results = getMoreResults();
                     lazyList.put(currentPage, results);
                }
                lazyLoadingHasMore();
           }
      
           @Override
           public T get(int i) {
                if (!lazyList.containsKey(i)) {
                     T results = getMoreResults();
                     lazyList.put(i, results);
                }
                return lazyList.get(i);
           }
      
           public void lazyLoadingHasMore() {
                hasMore = (getCurrentLoadedSize() > pageSize) ? true : false;
           }
      
           public void nextPage() {
                if (!isLastPage()) {
                     currentPage++;
                     lazyLoading();
                }
           }
      
           public void prevPage() {
                if (!isFirstPage()) {
                     currentPage--;
                     lazyLoading();
                }
           }
      
           public boolean isFirstPage() {
                return ( get(currentPage) != null ) && ( currentPage == 0 );
           }
      
           public boolean isLastPage() {
                return ( get(currentPage) != null ) && !hasMore;
           }
      
           @Override
           public int size() {return numberOfResults;}
      
           /** Accessors */
           public Map<Integer, T> getLazyList() {return lazyList;}
           public void setLazyList(Map<Integer, T> lazyList) {this.lazyList = lazyList;}
      
           public int getCurrentPage() {return currentPage;}
           public void setCurrentPage(int currentPage) {this.currentPage = currentPage;}
      
           public boolean isHasMore() {return hasMore;}
           public void setHasMore(boolean hasMore) {this.hasMore = hasMore;}
      
      }
      



      And its implentation :
      The problem is with the choixCatalogue variable...but i don't understand why because it works if a merge the two files...



      @Name("catalogue")
      @Scope(ScopeType.CONVERSATION)
      public class CatalogueAction extends LazyList<CataloguePageList> {
      
           private static final long serialVersionUID = -7606638159326958137L;
      
           @Logger Log logger;
      
           @In EntityManager entityManager;
      
           private int choixCatalogue = 0;
           private Long typeProduitId;
      
           @Override
           public void create() {
                super.create();
                if (typeProduitId == null) {
                     choixCatalogue = 0;
                     getFirstResults();
                }
           }
      
           public void rechercherCatalogue() {
                reset();
                lazyLoading();
           }
      
           public void switchCatalogue() {}
      
           @Override
           public void getFirstResults() {
                reset();
                this.get(currentPage);
           }
      
           @Override
           public CataloguePageList getMoreResults() {
                if (this.getChoixCatalogue()==0) {
                     return extractFromOffre(findAllOffres());
                }
                return null;
           }
      
           @Override
           public int getCurrentLoadedSize() {
                return ((CataloguePageList)this.get(this.getCurrentPage())).size();
           }
      
           public CataloguePageList extractFromOffre(List<Offre> listeOffres) {
                List<CatalogueProxy> listeProxys = new ArrayList<CatalogueProxy>();
                for (Offre offre : listeOffres) {
                     listeProxys.add(new CatalogueProxy(offre.getId(),"Offre",offre.getNom(),offre.getDescription()));
                }
                return new CataloguePageList(listeProxys);
           }
      
           /** Query */
           @SuppressWarnings("unchecked")
           public List<Offre> findAllOffres() {
                some code...
           }
      
           /** Accessors */
           public List<CatalogueProxy> pageCourrante() {return ((CataloguePageList)get(currentPage)).getPageList();}
      
           public int getChoixCatalogue() {return choixCatalogue;}
           public void setChoixCatalogue(int choixCatalogue) {this.choixCatalogue = choixCatalogue;}
      
           public Long getTypeProduitId() {return typeProduitId;}
           public void setTypeProduitId(int typeProduitId) {this.typeProduitId = new Long(typeProduitId);}
      
      }



      the page.xml :



      <page view-id="/catalogue.xhtml">
           <param name="choixCatalogue" value="#{catalogue.choixCatalogue}"/>
           <param name="typeProduitId" value="#{catalogue.typeProduitId}"/>
           <begin-conversation flush-mode="MANUAL" join="true"/>
      </page>




      and the catalogue.xhtml view, that's it there is no other EL expressions in this view (no display of the list) :



       <h:form id="searchForm">
           <a:region>
                   <h:outputText styleClass="label" value="Catalogue : "/>
                <h:selectOneMenu value="#{catalogue.choixCatalogue}" required="true">
                     <f:selectItem itemValue="0" itemLabel="Offres promotionnelles"/>
                     <f:selectItem itemValue="1" itemLabel="L'ensemble des produits Enov"/>
                     <a:support event="onchange" reRender="typeProduitSelect" action="#{catalogue.switchCatalogue}"/>
                </h:selectOneMenu>
           </a:region>
           <br />
           <a:outputPanel id="typeProduitSelect">
                <rich:panel rendered="#{catalogue.choixCatalogue == 1}">
                       <h:outputText styleClass="label" value="Produits : "/>
                       <h:selectOneMenu value="#{catalogue.typeProduitId}" required="true">
                             <f:selectItem itemValue="0" itemLabel="tous les produits"/>
                          <s:selectItems value="#{listeTypeProduitsNoeud}" var="_type" 
                                                itemValue="#{_type.id}" label="#{_type.nom}" />
                     </h:selectOneMenu>
                </rich:panel>
           </a:outputPanel>
                                    
           <br />
                                      
           <h:commandLink action="#{catalogue.rechercherCatalogue}" styleClass="link">
                 <h:outputText styleClass="linkTextButton" escape="false" value="#{messages['enov.menu.button.recherche']}"/>
               </h:commandLink>
      </h:form>




      Even if there is a error, the create() is ok. Everything is loaded in the lazylist when i log the whole thing...
      I have just notice that all my views are no longer avalaible to display...with all the same error...


      Have you some clues to help me solve this problem?


      Thanks in advance, and sorry for my bad bad bad english...and code!
      Bye.



        • 1. Re: Field error in seam bean
          Daniel Yokomizo Newbie

          Just stumbled upon this same issue today:


          In EL you can't access a property from a list (neither from a map). So, in the OP catalogue instanceof List == true, therefore the context for evaluation is a list context and javax.el.ListELResolver is used. This class tries to convert the property choixCatalogue into an int, but this fails. Removing the inheritance makes catalogue instanceof List == false and a regular resolver is used.

          • 2. Re: Field error in seam bean
            Martin Höller Newbie

            Hi!


            It seems I'm having the same problem: Accessing properties of an entry within a dataTable leads to NumberFormatExceptions when I have code like this:


            <rich:dataTable var="e" value="#{myList}">
              <rich:column>
                <f:facet name="header">
                  <h:outputText value="Name"/>
                </f:facet>
                <h:outputText value="#{e.name}"/>
              </rich:column>
            </rich:dataTable>
            



            When I change the access of the name property to the following, everything works fine.


            <rich:dataTable var="e" value="#{myList}">
              <rich:column>
                <f:facet name="header">
                  <h:outputText value="Name"/>
                </f:facet>
                <h:outputText value="#{e.getName()}"/>
              </rich:column>
            </rich:dataTable>
            



            The stacktrace is exactly as from the OP, so it seems a ListELResolver ist used which is totally unclear to me. e ist not a list but an entry from a list! When I output #{e.getClass()} it prints the entitie's class and not java.lang.List as suggested by Daniel.


            Can someone shade some more light on this?


            Many thanks in advance,


            - martin

            • 3. Re: Field error in seam bean
              Martin Höller Newbie

              I missed one important detail on my entity class (which wasn't implemented by me): it implements java.lang.List and that's likely to be the reason for ListELResolver to be selected. Why the ListELResolver want's to convert the property's name to a number is another question, but I'm sure, there is also a reason for this.


              Thanks for reading,
              - martin