12 Replies Latest reply on May 25, 2009 12:41 AM by berkay.berqui.gmail.com

    Using Enums for Radio Button Choices

    darthmaul

      I am attempting to use an enum as the basis for a set of radio button options.  Nothing exciting I know, but I am simply not sure how to reference the enum in my facelet. 


      Here is my enum:


      public enum OrderType implements Serializable {
         REGULAR_ORDER { public String getTypeAsString() { return "Regular Order"; } },
         QUOTE { public String getTypeAsString() { return "Quote"; } },
         RUSH_ORDER { public String getTypeAsString() { return "Rush Order"; } },
      };
      
         public abstract String getTypeAsString();
      }
      



      And I want to do something like this in my facelet:


      <h:selectOneRadio id="orderTypes" value="#{order.orderType}">
                  <f:selectItems value="#{orderTypes}"/>
                  <s:convertEnum />
      </h:selectOneRadio>
      




      ...where orderTypes would be a Seam component representing my enum.


      However, I imagine the enum cannot be a Seam component called orderTypes because it cannot be instantiated.  So how do I reference it in the facelet?


      Thanks for any insight 

        • 1. Re: Using Enums for Radio Button Choices
          billevans

          May I suggest you add a method to your 'order' Object that simply returns a List of SelectItems, where each SelectItem is an index into your enum. Then reference this method in your JSF page.



          public List<SelectItem> getOrderTypes() {
              List<SelectItem> list = new ArrayList<SelectItem>();
              for (OrderType t : OrderType.values()) {
                  list.add(new SelectItem(t.index, t));
              }
              return list;
          }  


          • 2. Re: Using Enums for Radio Button Choices

            This works for me:


            xhtml


            <h:selectOneMenu value="#{adminAddProduct.product.category}" class="inputText">
                 <s:selectItems value="#{adminAddProduct.categories}" var="category" label="#{category.resourceBundleName}" />
                 <s:convertEnum />
            </h:selectOneMenu>
            



            AdminAddProduct.java


            public Category[] getCategories() {
               return Category.values();
            }
            



            And then just a setter for the category in the 'product' entity.
            ResourceBundleName is something like your typeAsString.

            • 3. Re: Using Enums for Radio Button Choices
              pmuir

              Bill Evans wrote on May 15, 2008 06:55 AM:


              May I suggest you add a method to your 'order' Object that simply returns a List of SelectItems, where each SelectItem is an index into your enum. Then reference this method in your JSF page.



              Bad idea, as it couples your business layer to your view layer. Much better to use <s:selectItems />

              • 4. Re: Using Enums for Radio Button Choices
                darthmaul

                Thanks for your suggestions.


                Bill, your approach was what I was considering as a last resort.  As Pete suggested, I am hesitant to take that approach because I don't want my code to know it is being referenced by a JSF view.  Still, your approach works, and that is what matters above all academic or philosophical concerns.  I was just searching for a better way if I could find one.


                Daniel, your approach seems to be just what I was looking for.  It is still not the ideal approach I envisioned since you need to   expose the enum through another layer rather than get at it directly.  As a result, the Product class has another method added to its interface that seems extraneous since it adds nothing to its business-level capability.  I suppose though that this other academic concern is unavoidable given that Seam seems unable to get at an enum directly.


                Thanks again for your help.  

                • 5. Re: Using Enums for Radio Button Choices
                  darthmaul

                  I have tried Daniel's approach in this manner:


                  <h:selectOneRadio id="orderTypes" value="#{order.orderType}">
                              <s:selectItems var="orderType" value="#{interfaceUtility.orderTypes}" label="#{orderType.typeAsString}"/>
                              <s:convertEnum />
                  </h:selectOneRadio>
                  



                  where interfaceUtility has this method:



                  public OrderType[] getOrderTypes() {
                        return OrderType.values();
                  }
                  




                  But I got this exception:


                  java.lang.IllegalArgumentException: Cannot convert QUOTE of type class com.myapp.persistence.OrderType$2 to class com.myapp.persistence.OrderType$1
                       at org.jboss.el.lang.ELSupport.coerceToType(ELSupport.java:358)
                       at org.jboss.el.ExpressionFactoryImpl.coerceToType(ExpressionFactoryImpl.java:46)
                       at org.jboss.seam.el.SeamExpressionFactory.coerceToType(SeamExpressionFactory.java:70)
                       at com.sun.faces.renderkit.html_basic.RadioRenderer.renderOption(RadioRenderer.java:87)
                       at com.sun.faces.renderkit.html_basic.SelectManyCheckboxListRenderer.encodeEnd(SelectManyCheckboxListRenderer.java:146)
                       at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:836)
                       at org.ajax4jsf.renderkit.RendererBase.renderChild(RendererBase.java:286)
                       at org.ajax4jsf.renderkit.RendererBase.renderChildren(RendererBase.java:262)
                       at org.richfaces.renderkit.html.ModalPanelRenderer.doEncodeChildren(ModalPanelRenderer.java:397)
                       at org.richfaces.renderkit.html.ModalPanelRenderer.doEncodeChildren(ModalPanelRenderer.java:392)
                       at org.ajax4jsf.renderkit.RendererBase.encodeChildren(RendererBase.java:121)
                       at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:812)
                       at javax.faces.component.UIComponent.encodeAll(UIComponent.java:886)
                       at javax.faces.component.UIComponent.encodeAll(UIComponent.java:892)
                       at javax.faces.component.UIComponent.encodeAll(UIComponent.java:892)
                       at com.sun.facelets.FaceletViewHandler.renderView(FaceletViewHandler.java:577)
                       at org.ajax4jsf.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:108)
                       at org.ajax4jsf.application.AjaxViewHandler.renderView(AjaxViewHandler.java:189)
                       at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:106)
                       at com.sun.faces.lifecycle.LifecycleImpl.phase(LifecycleImpl.java:251)
                       at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:144)
                       at javax.faces.webapp.FacesServlet.service(FacesServlet.java:245)
                       at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:223)
                       at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:125)
                       at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:283)
                       at weblogic.servlet.internal.TailFilter.doFilter(TailFilter.java:26)
                       at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:42)
                       at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:83)
                       at org.jboss.seam.debug.hot.HotDeployFilter.doFilter(HotDeployFilter.java:68)
                       at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
                       at org.jboss.seam.web.MultipartFilter.doFilter(MultipartFilter.java:85)
                       at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
                  
                  



                  Any insight into the cause of the problem is appreciated.


                  Thanks.

                  • 6. Re: Using Enums for Radio Button Choices

                    I don't rally know why you get this, but ther seems to be some confusion with two diffrent kinds of ordertypes. Then you have that abstract thing which might be a bit weird to since you then, in some sense, have two OrderTypes. The abstract class and the classes(enums) extending it. My enum looked something like this, could you please try it (handwritten):


                    public enum OrderType implements Serializable {
                       REGULAR_ORDER("Regular Order"),
                       QUOTE("Quote"),
                       RUSH_ORDER("Rush Order");
                    
                       private String typeAsString;
                    
                       private OrderType(String typeAsString) {
                          this.typeAsString = typeAsString;
                       }
                    
                       public String getTypeAsString() { return typeAsString; }
                    };
                    
                    


                    • 7. Re: Using Enums for Radio Button Choices
                      darthmaul

                      It seems you were right.  For some reason, the abstract and concrete enums were causing issues.  I don't have any clue why since the abstract enum is obviously never instantiated.  Could this be a bug in the enumConverter? 


                      Well, I tried your approach, and things are working.


                      Thanks again, Daniel. 

                      • 8. Re: Using Enums for Radio Button Choices

                        Cool, glad I could help. I guess one could modify the EnumConverter to return the superclass of the enum or something like that to get rid of this small issue.

                        • 9. Re: Using Enums for Radio Button Choices
                          pmuir

                          It seems you were right. For some reason, the abstract and concrete enums were causing issues. I don't have any clue why since the abstract enum is obviously never instantiated. Could this be a bug in the enumConverter?

                          Perhaps - can you post the complete code for your enums as I don't quite follow what you have above.

                          • 10. Re: Using Enums for Radio Button Choices
                            darthmaul

                            Sure.  First, here is what did not work:


                            public enum OrderType implements Serializable {
                               REGULAR_ORDER { public String getTypeAsString() { return "Regular Order"; } },
                               QUOTE { public String getTypeAsString() { return "Quote"; } },
                               RUSH_ORDER { public String getTypeAsString() { return "Rush Order"; } },
                            };
                            
                               public abstract String getTypeAsString();
                            }
                            



                            Then, courtesy of Daniel, here is what did work:



                            public enum OrderType implements Serializable {
                               REGULAR_ORDER("Regular Order"),
                               QUOTE("Quote"),
                               RUSH_ORDER("Rush Order");
                            
                               private String typeAsString;
                            
                               private OrderType(String typeAsString) {
                                  this.typeAsString = typeAsString;
                               }
                            
                               public String getTypeAsString() { return typeAsString; }
                            };
                            



                            Let me know if you need more information.


                            Thanks.

                            • 11. Re: Using Enums for Radio Button Choices
                              pmuir

                              Ok, you have an  errant


                              ,
                              };



                              in there which was confusing me ;-)


                              I guess you can file a bug about this for <s:convertEnum /> as your enum syntax is valid (if slightly unusual ;-)

                              • 12. Re: Using Enums for Radio Button Choices
                                berkay.berqui.gmail.com

                                hi..
                                u can use seam's selectitems or tomahawks selectitems tag..




                                public enum Beer {
                                   DARK("beer.dark"),
                                   LIGHT("beer.light");
                                
                                   private String label;
                                
                                   private Beer(String label){
                                     this.label = label;
                                   }
                                }



                                then in your managed bean..




                                public List<Beer> getBeers(){
                                   return Arrays.asList(Beer.values());
                                }



                                in a facelet like..



                                <h:selectOneMenu value="#{managedBean.selectedEnumValue}">
                                <t:selectItems value="#{managedBean.beers}" var="beer" itemLabel="#{msg[beer.label]}" itemValue="#{beer}" /> 
                                </h:selectOneMenu>