5 Replies Latest reply on Apr 5, 2007 7:00 AM by greko

    Injection failed on form submit using rich:datatable binding

    greko

      Hi !

      I want to have the rows of my <rich:datatable> clickable.
      OnRowClick, i want to perform an ajax4jsf action using <a4j:support>.

      Here is my form :

       <h:form id="sampleAction">
       <h:commandButton id="sampleAction" value="sampleAction!"
       action="#{sampleAction.sampleAction}"/>
      
       <rich:dataTable id="tatable"
       cellpadding="0" cellspacing="0" width="700" border="0"
      
       value="#{sampleAction.myDataList}"
       var="myDataItem"
       binding="#{sampleAction.myDataTable}">
      
       <!-- This is what i want to do
       <a4j:support
       actionListener="#{sampleAction.rowSelected}"
       event="onRowClick" />
       -->
      
       <rich:column>
       <f:facet name="header">Select</f:facet>
       <h:outputText value="#{myDataItem}" />
       </rich:column>
       </rich:dataTable>
      
       </h:form>
      


      Here is my backing stateful bean :


      
      @Stateful
      @Name("sampleAction")
      @Scope(SESSION)
      public class SampleActionBean implements SampleAction {
      
       @Logger
       private Log log;
      
       @In(create=true)
       FacesMessages facesMessages;
      
       // seam-gen method
       public String sampleAction() {
       // implement your business logic here
       log.info("sampleAction.sampleAction() action called");
      // facesMessages.add("sampleAction");
       return "success";
       }
      
      
       // Properties ----------------------------------------------------------
       @DataModel
       public String[] myDataList = {"Valeur 1", "Valeur 2", "Valeur 3", "Valeur 4", "Valeur 5"};
       public String myDataItem;
       public UIData myDataTable;
      
       // Actions ----------------------------------------------------------
      
       public String rowSelected(ActionEvent event) {
       myDataItem = (String) getMyDataTable().getRowData();
       log.info("rowSelected ==> " + myDataItem);
       return "success";
       }
      
       public String getSelectedItem() {
       log.info("sampleAction.getSelectedItem() called");
       log.info("----> " + myDataItem);
      
       // Do your thing with the MyData item in myDataItem.
       //facesMessages.add("Get selected item : " + myDataItem);
      
       return "success"; // Navigation case.
       }
      
       public String getMyDataItem() {
       return myDataItem;
       }
      
       public void setMyDataItem(String myDataItem) {
       this.myDataItem = myDataItem;
       }
      
       public String[] getMyDataList() {
       return myDataList;
       }
      
       public void setMyDataList(String[] myDataList) {
       this.myDataList = myDataList;
       }
      
       public UIData getMyDataTable() {
       return myDataTable;
       }
      
       public void setMyDataTable(UIData myDataTable) {
       this.myDataTable = myDataTable;
       }
       @Destroy
       @Remove
       public void destroy() {
       }
      }
      
      


      BUT ... on submit (ajax or simple action with my <h:commandButton>) i have the following exception :

      
      19:26:02,890 ERROR [ExceptionFilter] exception root cause
      javax.faces.el.EvaluationException: /sampleAction.xhtml @31,47 binding="#{sampleAction.myDataTable}": Exception setting property myDataTable of base with class org.javassist.tmp.java.lang.Object_$$_javassist_1
       at com.sun.facelets.el.LegacyValueBinding.setValue(LegacyValueBinding.java:74)
       at org.apache.myfaces.shared_impl.util.RestoreStateUtils.recursivelyHandleComponentReferencesAndSetValid(RestoreStateUtils.java:70)
       at org.apache.myfaces.shared_impl.util.RestoreStateUtils.recursivelyHandleComponentReferencesAndSetValid(RestoreStateUtils.java:41)
       at org.apache.myfaces.shared_impl.util.RestoreStateUtils.recursivelyHandleComponentReferencesAndSetValid(RestoreStateUtils.java:78)
       at org.apache.myfaces.shared_impl.util.RestoreStateUtils.recursivelyHandleComponentReferencesAndSetValid(RestoreStateUtils.java:41)
       at org.apache.myfaces.lifecycle.LifecycleImpl.restoreView(LifecycleImpl.java:179)
       at org.apache.myfaces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:66)
       at javax.faces.webapp.FacesServlet.service(FacesServlet.java:137)
       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)
      
      ...
      
      Caused by: javax.ejb.EJBException: org.jboss.seam.RequiredException: In attribute requires non-null value: sampleAction.facesMessages
       at org.jboss.ejb3.tx.Ejb3TxPolicy.handleExceptionInOurTx(Ejb3TxPolicy.java:69)
       at org.jboss.aspects.tx.TxPolicy.invokeInOurTx(TxPolicy.java:83)
       at org.jboss.aspects.tx.TxInterceptor$Required.invoke(TxInterceptor.java:191)
      
      


      It's just like if my injected facesMessages is not injected after a submit.

      If I dont use any @In-jected attribute, it works.
      If i do, the bind="..." attribute of my <rich:dataTable> makes me go into troubles...

      Please, any idea ?

        • 1. Re: Injection failed on form submit using rich:datatable bin
          greko

          BTW, I use :
          * Seam 1.2.1
          * Ajax4Jsf 1.1.1-SNAPSHOT
          * richfaces-3.0.1-SNAPSHOT

          The same happens using :
          * Seam 1.2.0
          * Ajax4Jsf 1.1.0
          * richfaces-3.0.0


          Thx in advance :)

          • 2. Re: Injection failed on form submit using rich:datatable bin

            you perform binding in wrong way. facesMessages is not available at restoreView phase.

            Binding with Session scope bean is glitchable approach. The same sort of glitches you can get without any ajax if you have several pages with this table open simultaneously.

            • 3. Re: Injection failed on form submit using rich:datatable bin
              greko

              Thank you for your answer.

              I think I understand now.

              I found a work around, which may be a more standard use of Seam + RichFaces.

              It looks like this :

               <rich:dataTable
               id="data_list"
               cellpadding="0" cellspacing="0" width="700" border="0"
               value="#{myDataList}"
               var="p">
              
               <a4j:support
               actionListener="#{sampleAction.selectRow(p)}"
               event="onRowClick"
               reRender="valval" />
              
               <rich:column>
               <f:facet name="header">Item</f:facet>
               <h:outputText value="#{p}" />
               </rich:column>
              
               </rich:dataTable>
              
              


              ... and this

               // Properties ----------------------------------------------------------
               @DataModel("myDataList")
               public List<String> myDataList;
              
               @DataModelSelection
               @Out(required = false)
               public String myDataItem;
              
              
               // Methods ----------------------------------------------------------
              
               @SuppressWarnings("unchecked")
               @Factory("myDataList")
               public void getMyDataList() {
               myDataList = new ArrayList();
               myDataList.add("Value 1");
               myDataList.add("Value 2");
               myDataList.add("Value 3");
               myDataList.add("Value 4");
               myDataList.add("Value 5");
               myDataList.add("Value 6");
              
               }
              
               public void selectRow(String data) {
               log.info("===> " + data);
               myDataItem = data;
               }
              


              It works pretty good.
              Is it a good way to do my row selection ?

              BTW, is it possible to have a <a4j:support event="onRowClick"> plus a onRowClick="" attribute for my <rich:datatable> ??

              Because I'd like to add some javascript to colorize my selected row.


              Thanks for your answers ;)
              Greg

              • 4. Re: Injection failed on form submit using rich:datatable bin
                ilya_shaikovsky

                You may use onsubmit attribute of the a4j:support. So your colorer JS will be called with the ajax request after the same event.

                • 5. Re: Injection failed on form submit using rich:datatable bin
                  greko

                  Thanks !

                  ... but from there, I can't have my row JS object using 'this' ...
                  I'll have to find another way to do it...