14 Replies Latest reply on Sep 27, 2006 5:47 PM by Patraphong Sukhonpitumart

    AJAX4JSF: Problems with validation.

    hdslkf hklsdg Apprentice

      First of all: Yes I know, this isn't a pure Seam topic and it usually doesn't belong here. BUT

      1. There are 2 weeks left for me to solve this single issue. If I don't suceed I'll have to fallback to static stuff :(. have mercy with me ;).
      2. The Exadel forum is quite empty, and the forum here is full of experts.
      3. Using Seam and AJAX4JSF together is quite interesting, since both enable you to easily create great webapps. They complement one another, and many Seam developers might encounter the same prob.


      Ok, now the prob: I have the following code:

      What are you interested in?
      <h:selectOneMenu value="#{bean.interested}" required="true">
       <f:selectItems value="#{backingBean.interestedOptions}" />
       <a4j:support event="onchange" reRender="menu2" ajaxSingle="true" />
      </h:selectOneMenu>
      
      And which is your favourite?
      <h:selectOneMenu id="menu2" value="#{bean.favourite}" required="true">
       <f:selectItems value="#{backingBean.favouriteOptions}" />
      </h:selectOneMenu>
      
      Your name?
      <h:inputText value="#{bean.name}" required="true" />


      You can see that I have 3 inputs and they all require to be filled. The second selectOneMenu is initially empty, since the choices depend on what you select in the first menu.

      Simple Example:

      - You select "hockey" in menu 1, and then menu 2 offers a list of hockey teams.
      - You select "cars" in menu 1, menu 2 offers car brands etc.

      Those updates shall be done via AJAX4JSF.

      Every select menu has a top (invalid) entry "---" to show the user that he should select something here. It's important that there aren't any pre-selected entries since this might lead to accidently chosen but unwanted options.

      Ok, now my problem: Whenever menu 1 is changed, AJAX4JSF submits the menu 1 selection and starts the complete JSF lifecycle including validation... for ALL input fields. And if validation fails, the AJAX update does not succeed and everything remains like it was.

      Scenario 1: I use ajaxSingle="true" to submit only the changed selection. Then validation will fail since there's no value submitted for the second select menu. (Plus: if there is any field marked invalid during a previous form submit, it stays invalid and causes a validation fault here, too).

      Scenario 2: I don't use ajaxSingle="true" and all fields of the form are submitted upon selection change in menu 1. Then validation will fail, too, if there is any empty or invalid field. And this might occur very often, since you can't force a user to first fill in all text fields and then perform selection.

      Any scenario will drive the user mad - and me, too ;). And it's not only this select menu possibility. There are many other real life application situations where a AJAX4JSF request might fail.

      Long explanation, short conclusion: I'd need a way to prevent JSF to validate any field other then the changed one. Skipping the whole validation during AJAX processing would be nice, too (unfortunately there's no immeditate="true" like in JSF action commands... well ok, there is such an attribute, but it has a completely different meaning).

      I could completely leave out JSF validation here and put it in my business logic (if something is not filled in correctly, I add a message and redisplay the page)... but hey, that's crazy ;).

      Soooo... anyone out there... experienced with this problem? Solved it? Give me a hint ;).

        • 1. Re: AJAX4JSF: Problems with validation.
          Patraphong Sukhonpitumart Newbie

          I'm having the same problem, either with or without ajax.

          Anyway, a UIInput does have the immediate attribute. But it doesn't help very much as the input value is stored (during apply request phase) in the component, not in the model.

          Now i can only think of a solution -- setting fields' immediate attributes to "true" and getting values via component bindings. But.. this is.. weired, IMO.

          • 2. Re: AJAX4JSF: Problems with validation.
            hdslkf hklsdg Apprentice

            That's an interesting approach. One can invoke an action in the a4j:support tag and via immediate="true" it gets executed during APPLY_REQUEST_VALUES - so this would be possible. But yes, it is weird and I refrain from using this *brrr* ;).

            I even tried out a4j:region and multiple other tags, but they couldn't help me. But I must confess that I just try out blindly and that I didn't get smarter by reading the documentation (parts of it are really not easy to understand for a non-native speaker like me ;)).

            • 3. Re: AJAX4JSF: Problems with validation.
              Johannes Behrndt Newbie

              I'm not sure, since I am also just starting with Ajax4Jsf...
              But wouldn't it work for you to just include the first selectOneMenu in a region with renderRegionOnly set to false so that on submit only this region is submitted but components outside the region can also be updated in the response?

              • 4. Re: AJAX4JSF: Problems with validation.
                Patraphong Sukhonpitumart Newbie

                I ended up using seam remoting. The only drawback (?) is that you have to deal with javascript.

                • 5. Re: AJAX4JSF: Problems with validation.
                  hdslkf hklsdg Apprentice

                  How do you handle select items? Does it work? If yes could you give me a short extract of your code? I'm really a little exhausted and I'd be very thankful if you could save my weekend :).

                  • 6. Re: AJAX4JSF: Problems with validation.
                    Patraphong Sukhonpitumart Newbie

                    It works. Just add an onchange event handler to your controlling component. The handler makes an async call to a remote method with the selected value as a parameter. (Seam.Component.getInstance('yourBeanName').yourMethod(param)) When the response is received, a callback method is called. It then fills the select options with the 'things' it's got.

                    • 7. Re: AJAX4JSF: Problems with validation.
                      Patraphong Sukhonpitumart Newbie

                      See chapter 7 of the ref.

                      • 8. Re: AJAX4JSF: Problems with validation.
                        hdslkf hklsdg Apprentice

                        I thought it would be more difficult (I remember some thread here where one had problems with a select menu). Thanks for your tip ;).

                        • 9. Re: AJAX4JSF: Problems with validation.
                          hdslkf hklsdg Apprentice

                          I finally found the solution (or let's say wcasatti from Exadel forum told me how to do it right):

                          With the a4j:region tag you can define which components shall be decoded during the JSF lifecycle. This is where the language barrier was a problem for me since didn't understand that "decode" meant "process" (but I think some native speakers didn't catch that either *g*).

                          So if define a a4j:region around the select menu 1 then only this single component is validated. That's what I wanted. But in order to create the output for the new menu 2 I need to set the attribute renderRegionOnly to "false", so that the other components are included in the AJAX response, too.

                          Well, here's the code:

                          <a4j:region renderRegionOnly="false">
                           <h:selectOneMenu id="menu1" value="..." required="true">
                           <f:selectItems ... />
                           <a4j:support event="onchange" reRender="menu2" />
                           </h:selectOneMenu>
                          </a4j:region>
                          
                          <h:selectOneMenu id="menu2" ....
                          ....


                          PS: I think that the attribute ajaxSingle should be deprecated. It might leads to problems and a4j:region does it much better :).

                          • 10. Re: AJAX4JSF: Problems with validation.
                            Johannes Behrndt Newbie

                            Yepp, that's what I tried to explain... ;-)

                            "johnnybe" wrote:
                            But wouldn't it work for you to just include the first selectOneMenu in a region with renderRegionOnly set to false so that on submit only this region is submitted but components outside the region can also be updated in the response?


                            • 11. Re: AJAX4JSF: Problems with validation.
                              hdslkf hklsdg Apprentice

                              You're right. I tried out a lot with regions, too, but somehow I misunderstood you completely. But ok, the problem is that I first didn't catch at all what regions are good for ;). Thanks again for your help, though I was to dumb to adapt it *g*.

                              • 12. Re: AJAX4JSF: Problems with validation.
                                hdslkf hklsdg Apprentice

                                Another huge bunch of s...uper nice probs with AJAX4JSF. It screws up my DOCTYPE definition as it automatically adds

                                <?xml version="1.0"?>
                                to the top of any processed document and displaces the doctype definition downwards. And since Internet Explorer only parses the very first line for a doctype it falls back to quirks mode and the whole CSS stuff is hosed.

                                Try it out, and change the beginning of the web.xml of the booking example:
                                <!-- Seam -->
                                
                                 <listener>
                                 <listener-class>org.jboss.seam.servlet.SeamListener</listener-class>
                                 </listener>
                                
                                
                                 <!-- Propagate conversations across redirects -->
                                 <filter>
                                 <filter-name>Seam Redirect Filter</filter-name>
                                 <filter-class>org.jboss.seam.servlet.SeamRedirectFilter</filter-class>
                                 </filter>
                                
                                
                                 <!-- ajax4jsf -->
                                
                                 <filter>
                                 <display-name>Ajax4jsf Filter</display-name>
                                 <filter-name>ajax4jsf</filter-name>
                                 <filter-class>org.ajax4jsf.Filter</filter-class>
                                 </filter>
                                
                                 <!-- filter-mapping>
                                 <filter-name>ajax4jsf</filter-name>
                                 <servlet-name>Faces Servlert</servlet-name>
                                 <dispatcher>REQUEST</dispatcher>
                                 <dispatcher>FORWARD</dispatcher>
                                 <dispatcher>INCLUDE</dispatcher>
                                 </filter-mapping -->
                                
                                 <filter-mapping>
                                 <filter-name>ajax4jsf</filter-name>
                                 <url-pattern>*.bosch</url-pattern>
                                 </filter-mapping>
                                
                                 <context-param>
                                 <param-name>org.ajax4jsf.VIEW_HANDLERS</param-name>
                                 <param-value>com.sun.facelets.FaceletViewHandler</param-value>
                                 </context-param>
                                
                                 <filter-mapping>
                                 <filter-name>Seam Redirect Filter</filter-name>
                                 <url-pattern>*.bosch</url-pattern>
                                 </filter-mapping>

                                Plus add ajax4jsf.jar from https://ajax4jsf.dev.java.net/nonav/ajax/ajax-jsf/download.html#binary to $JBOSS_HOME\server\default\deploy\jbossweb-tomcat55.sar\jsf-libs

                                See it with your own eyes. The booking example looks totally goofed (and I used it as a template for my own app *sigh*).

                                I contacted Sergey Smirnov, but since my recent question at Exadel took quite long I wanted to ask you for experiences with this issue.[/url]

                                • 13. Re: AJAX4JSF: Problems with validation.
                                  hdslkf hklsdg Apprentice

                                  Yes, found the solution :)

                                  <filter>
                                   <display-name>Ajax4jsf Filter</display-name>
                                   <filter-name>ajax4jsf</filter-name>
                                   <filter-class>org.ajax4jsf.Filter</filter-class>
                                   <init-param>
                                   <param-name>forceparser</param-name>
                                   <param-value>false</param-value>
                                   </init-param>
                                   </filter>


                                  • 14. Re: AJAX4JSF: Problems with validation.
                                    Patraphong Sukhonpitumart Newbie

                                    Wow, bfo81, that was great! Thanks for sharing.

                                    Personally I don't think seam (with facelets running on jboss) would work well with ajax4jsf because of the classloading problem. To use a4j, I removed some jars from my app and put them in jsf-libs. I later wanted to use jenia4faces and then messed up with even more jars.

                                    ... I'm thinking about not using ajax4jsf (until I get a better solution) as I don't want to put everything inside jsf-libs.