13 Replies Latest reply on Oct 31, 2006 1:49 PM by gavin.king

    Submitting using SelectOneRadio

    monkeyden

      I'm not sure where this should be posted, as it's in a grey area.

      I'm using the following reference to submit using a SelectOneRadio.

      http://wiki.apache.org/myfaces/JavascriptWithJavaServerFaces

      Everything works as promised in the example (the listener method is called) but I have one other requirement. I need to value of the selected radio button to be passed to my listener method. My locationsByState() listener is traversing a cached list of SelectItems, to return the ones that have a description value of whatever @RequestParameter selectedState is. The problem is, selectedState is always null. I think I'm misunderstanding what happens when the commandLink is processed. I'm assuming the value would be submitted when the commandButton is programatically "clicked."

      I have set it up in the Seam action as follows (staticLocations is a globally cached list of locations):

      @RequestParameter
      private String selectedState;
      
      public List<SelectItem> locationsByState(){
       List<SelectItem> locationsByState = new ArrayList<SelectItem>();
       loadLocations();
       for(int i=0;i<staticLocations.size();i++){
       SelectItem current = staticLocations.get(i);
       //selectedState is always null
       if(current.getDescription().trim().equals(selectedState)){
       locationsByState.add(current);
       }
       }
       return locationsByState;
       }
      
      


      In the view, radioSubmit() is generating a JS event for "hiddenLink", to call the listener method. Again, everything works exactly as expected.

      <h:selectOneRadio value="#{editProfileAction.selectedState}" onmouseup="radioSubmit('hiddenLink');" styleClass="bodyCopy">
       <f:selectItem itemLabel="MA" itemValue="MA"/>
       <f:selectItem itemLabel="ME" itemValue="ME"/>
       <f:selectItem itemLabel="NH" itemValue="NH"/>
       <f:selectItem itemLabel="RI" itemValue="RI"/>
       <f:selectItem itemLabel="VT" itemValue="VT"/>
      </h:selectOneRadio>
      
      <t:commandLink id="hiddenLink" forceId="true"
       style="display:none; visibility:hidden;"
       action="#{editProfileAction.locationsByState}">
      </t:commandLink>
      
      


        • 1. Re: Submitting using SelectOneRadio
          monkeyden

          Sorry, hosed the action method (needs to return String), but the main problem is still the same. Can't force the radio button's value into the Seam component.

          public String locationsByState(){
           currentLocations = new ArrayList<SelectItem>();
           loadLocations();
           Context event = Contexts.getEventContext();
           Context session = Contexts.getSessionContext();
           Context page = Contexts.getPageContext();
           for(int i=0;i<staticLocations.size();i++){
           SelectItem current = staticLocations.get(i);
           if(current.getDescription().trim().equals(selectedState)){
           currentLocations.add(current);
           }
           }
           setSelectedTab(1);
           return display();
          }


          • 2. Re: Submitting using SelectOneRadio
            monkeyden

            I've implemented a ValueChangeListener, to handle the change of the radio button, but I'm not sure how to change the value in my Seam component, to reflect the value change. I'm sure I am supposed to be looking up the Seam component a different way, since it fails with a ClassCastException when I try to get the Seam component from FacesContext.

            The question now is, in what way is this code different when we're dealing with Seam components (SFSBs) vs. standard JSF managed beans? It finds the component just fine, and even tells me the beanClass is com.project.actions.EditUserRecordAction.

            Here is the code:


            package com.project.util;
            
            import javax.faces.application.Application;
            import javax.faces.context.FacesContext;
            import javax.faces.event.AbortProcessingException;
            import javax.faces.event.ValueChangeEvent;
            import javax.faces.event.ValueChangeListener;
            
            import com.project.actions.EditUserRecordAction;
            
            public class StateSelectorChangeListener implements ValueChangeListener {
            
             public void processValueChange(ValueChangeEvent event) throws AbortProcessingException {
             FacesContext facesContext = FacesContext.getCurrentInstance();
             Application app = facesContext.getApplication();
             Object myObj = app.getVariableResolver().resolveVariable(facesContext, "editProfileAction");
             try {
             EditUserRecordAction editRecordBean = (EditUserRecordAction)myObj;
             editRecordBean.setSelectedState((String)event.getNewValue());
             } catch (RuntimeException e) {
             e.printStackTrace();
             }
             }
            
            }
            


            @Stateful
            @Name("editProfileAction")
            @Scope(SESSION)
            public class EditUserRecordAction implements EditUserRecord, Serializable {
             ...
             public void setSelectedState(String selectedState){
             this.selectedState = selectedState;
             }
            }





            • 3. Re: Submitting using SelectOneRadio
              monkeyden

              Sorry to be so noisy on an ignored topic. I have degraded to a much simpler question. Has anyone gotten the valueChangeListener attribute to work with <h:selectOneRadio>? I have seen a handful of threads around and no one has ultimately said that they got it to work. The result in my case is a very mysterious NoSuchMethodException, though I clearly have it defined in the interface and the implementation of my SFSB. How can this possibly be the case? In desperation, I've tried tweaking the InterceptionType, to no avail. Do I need a [currently unknown] annotation on this method?

              <h:selectOneRadio immediate="true"
               id="stateRadios"
               value="#{editProfileAction.selectedState}"
               onclick="submit()" valueChangeListener="#{editProfileAction.updateStateRadioChange}">
               <f:selectItem itemLabel="MA" itemValue="MA"/>
               <f:selectItem itemLabel="ME" itemValue="ME"/>
               <f:selectItem itemLabel="NH" itemValue="NH"/>
               <f:selectItem itemLabel="RI" itemValue="RI"/>
               <f:selectItem itemLabel="VT" itemValue="VT"/>
              </h:selectOneRadio>


              public void updateStateRadioChange(ValueChangeEvent event);


              public void updateStateRadioChange(ValueChangeEvent event){
               this.selectedState = (String)event.getNewValue();
              }


              Caused by: java.lang.NoSuchMethodException: updateStateRadioChange


              • 4. Re: Submitting using SelectOneRadio
                gavin.king

                Can you make it work for a h:inputText?

                • 5. Re: Submitting using SelectOneRadio
                  monkeyden

                  no, that's the first thing I tried, because it's a boolean component. I saw the same result. When that didn't work, it occurred to me that the type of component might not even matter, so long as the ValueChangeEvent was created. Note, this is all done after obsessively cleaning my project, JBoss tmp+work folders and deleting the ear.

                  BTW, this is Seam 1.0.1. To change versions right now would probably make this project all the more tragic.

                  • 6. Re: Submitting using SelectOneRadio
                    gavin.king

                    It would help if you showed us the stack trace.

                    • 7. Re: Submitting using SelectOneRadio
                      monkeyden

                      NOTE: I abandoned implementation of a ValueChangeListener (earlier posts in this thread), in favor of invoking the value change listener method on the Seam component instance itself.

                      20:31:23,711 ERROR [[Faces Servlet]] Servlet.service() for servlet Faces Servlet threw exception
                      javax.faces.el.EvaluationException: Exception while invoking expression #{editProfileAction.updateStateRadioChange}
                       at org.apache.myfaces.el.MethodBindingImpl.invoke(MethodBindingImpl.java:165)
                       at org.jboss.seam.actionparam.ActionParamBindingHelper.invokeTheExpression(ActionParamBindingHelper.java:58)
                       at org.jboss.seam.actionparam.ActionParamMethodBinding.invoke(ActionParamMethodBinding.java:71)
                       at javax.faces.component.UIInput.broadcast(UIInput.java:200)
                       at javax.faces.component.UIViewRoot._broadcastForPhase(UIViewRoot.java:90)
                       at javax.faces.component.UIViewRoot.processDecodes(UIViewRoot.java:132)
                       at org.apache.myfaces.lifecycle.LifecycleImpl.applyRequestValues(LifecycleImpl.java:200)
                       at org.apache.myfaces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:71)
                       at javax.faces.webapp.FacesServlet.service(FacesServlet.java:106)
                       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)
                       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
                       at org.apache.myfaces.webapp.filter.ExtensionsFilter.doFilter(ExtensionsFilter.java:144)
                       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
                       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
                       at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
                       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
                       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
                       at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
                       at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178)
                       at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:175)
                       at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:74)
                       at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126)
                       at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105)
                       at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107)
                       at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148)
                       at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:869)
                       at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:664)
                       at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:527)
                       at org.apache.tomcat.util.net.MasterSlaveWorkerThread.run(MasterSlaveWorkerThread.java:112)
                       at java.lang.Thread.run()V(Unknown Source)
                      Caused by: java.lang.NoSuchMethodException: updateStateRadioChange
                       at java.lang.Class.findMethod(Ljava.lang.String;[Ljava.lang.Class;I)Ljava.lang.reflect.Method;(Unknown Source)
                       at java.lang.Class.getMethod(Ljava.lang.String;[Ljava.lang.Class;I)Ljava.lang.reflect.Method;(Unknown Source)
                       at org.apache.myfaces.el.MethodBindingImpl.invoke(MethodBindingImpl.java:118)
                       ... 29 more


                      • 8. Re: Submitting using SelectOneRadio
                        gavin.king

                        Put a breakpoint in the MyFaces code and find out what values it is passing to getMethod().

                        • 9. Re: Submitting using SelectOneRadio
                          monkeyden

                          Here is the runtime memory (up to the call to org.apache.myfaces.el.MethodBindingImpl.getMethod()). _argClasses is null, which tells me that it might be expecting to call a no-arg method, when the actual method takes a ValueChangeEvent.

                          this MethodBindingImpl (id=346)
                          facesContext ServletFacesContextImpl (id=347)
                          args Object[0] (id=348)
                          baseAndProperty Object[2] (id=349)
                           [0] Proxy$$EnhancerByCGLIB$$f38c8c2a (id=298)
                           CGLIB$BOUND true
                           CGLIB$CALLBACK_0 ClientSideInterceptor (id=310)
                           CGLIB$CONSTRUCTED true
                           [1] "updateStateRadioChange"
                          base Proxy$$EnhancerByCGLIB$$f38c8c2a (id=298)
                           CGLIB$BOUND true
                           CGLIB$CALLBACK_0 ClientSideInterceptor (id=310)
                           bean $Proxy116 (id=319)
                           component Component (id=317)
                           beanClass Class<T> (com.project.actions.EditUserRecordAction) (id=264)
                           businessInterfaces HashSet<E> (id=357)
                           clientSideInterceptors ArrayList<E> (id=361)
                           createMethod null
                           dataModelFieldAnnotations HashMap<K,V> (id=362)
                           dataModelFields ArrayList<E> (id=366)
                           dataModelGetterAnnotations HashMap<K,V> (id=376)
                           dataModelGetters ArrayList<E> (id=377)
                           dataModelSelectionFieldAnnotations HashMap<K,V> (id=378)
                           dataModelSelectionFields HashMap<K,V> (id=379)
                           dataModelSelectionSetterAnnotations HashMap<K,V> (id=380)
                           dataModelSelectionSetters HashMap<K,V> (id=381)
                           dependencies null
                           destroyMethod Method (id=382)
                           factory Class<T> (org.jboss.seam.intercept.Proxy$$EnhancerByCGLIB$$f38c8c2a) (id=299)
                           inFields HashSet<E> (id=383)
                           initializerFields HashMap<K,V> (id=384)
                           initializerSetters HashMap<K,V> (id=385)
                           inMethods HashSet<E> (id=386)
                           interceptionType InterceptionType (id=387)
                           interceptors ArrayList<E> (id=389)
                           jndiName "pipeline/EditUserRecordAction/local"
                           logField Field (id=391)
                           logInstance LogImpl (id=393)
                           name "editProfileAction"
                           outFields HashSet<E> (id=395)
                           outMethods HashSet<E> (id=396)
                           parameterFields HashSet<E> (id=397)
                           parameterSetters HashSet<E> (id=398)
                           postActivateMethod null
                           postConstructMethod null
                           preDestroyMethod null
                           prePassivateMethod null
                           removeMethods HashSet<E> (id=399)
                           scope ScopeType (id=400)
                           startup false
                           synchronize true
                           timeout 1000
                           type ComponentType (id=402)
                           unwrapMethod null
                           validateMethods HashSet<E> (id=404)
                           validators Hashtable<K,V> (id=405)
                           componentName "editProfileAction"
                           isSeamComponent true
                           type InterceptorType (id=326)
                           userInterceptors ArrayList<E> (id=330)
                           CGLIB$CONSTRUCTED true
                          property "updateStateRadioChange"
                          


                          • 10. Re: Submitting using SelectOneRadio
                            monkeyden

                            I changed the method signature of updateStateRadioChange to no-arg, and it called it properly. It's looking like I'm completely misunderstanding the way in which a ValueChangeListener method is invoked.

                            It's my understanding that when the valueChangeListener attribute is specified for a component, JSF creates the ValueChangeEvent, on submit, and hands it to the listener method. Is this true?

                            • 11. Re: Submitting using SelectOneRadio
                              gavin.king

                              Can you try this with a CVS or nightly build of Seam, it looks like a bug that was already fixed.

                              • 12. Re: Submitting using SelectOneRadio
                                monkeyden

                                BINGO! Built from CVS. I never would have guessed that this was a bug in Seam. Seems to me that it has more to do with JSF event handling. Anyway, it's in the rear-view mirror. Thanks for the help Gavin.

                                • 13. Re: Submitting using SelectOneRadio
                                  gavin.king

                                  Yeah, usually something like this would not be a seam-related problem, but we hacked in some functionality to make JSF method bindings more flexible (and I screwed up doing it).