11 Replies Latest reply on May 17, 2006 4:47 AM by villo

    Strange behavior using JSTL (MyFaces)

    dahm

      Hi,

      the following problem may not be directly linked with Seam. However,
      I'm quite confused, so maybe you can help...

      I want to to use the forEach-Tag like in the following code (dummy.jsp)

      <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
      <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
      <%@ taglib uri="http://java.sun.com/jstl/core" prefix="c"%>
      
      <html>
      <head>
      <title>Dummy</title>
      </head>
      <body>
      <f:view>
       <h:outputText value="bla" />
       <h:outputText value="#{dummy.list}" />
       <c:forEach items="#{dummy.list}" var="vp">
       <div>Name: <h:outputText value="#{vp}" /></div>
       </c:forEach>
      </f:view>
      </body>
      </html>
      


      Yet the output is just:

      <html>
      <head>
      <title>Dummy</title>
      </head>
      <body>
       bla
       [Hello, World]
      
       <div>Name: </div>
      
      
      </div></body>
      </html>
      


      Notice that there are actually values in the list,
      it's just as if the c:forEach-Tag is completely ignored, while
      h:outputText works fine.

      Finally the code of the bean:

      @Stateless
      @Name("dummy")
      @Interceptors(SeamInterceptor.class)
      public class DummyBean implements Dummy {
       public List getList() {
       ArrayList<String> result = new ArrayList<String>();
       result.add("Hello");
       result.add("World");
      
       return result;
       }
      }
      


      I'm adding standard.jar to WEB-INF/lib by default. I also tried to put
      it directly into the deploy or default/lib directory or change the URI
      to http://java.sun.com/jsp/jstl/core.

      Alas, none of this worked. Do you have an idea why the above does occur?
      I've got the vague idea the #{} notation may not be appropriate, but
      ${} doesn't work.

      Cheers
      Markus

        • 1. Re: Strange behavior using JSTL (MyFaces)
          theute

          Mixing JSTL and JSF EL does not work well with JSF 1.1
          This is not related to Seam.

          • 2. Re: Strange behavior using JSTL (MyFaces)
            gavin.king

            Actually it works fine if you use facelets ;-)

            Just don't use JSP and your life will be much easier.

            • 3. Re: Strange behavior using JSTL (MyFaces)
              ssilvert

              Or, you can wait for JSF 1.2 and JSP 2.1. The Unified EL fixes this.

              See http://java.sun.com/developer/technicalArticles/J2EE/jsp_21/

              Stan

              • 4. Re: Strange behavior using JSTL (MyFaces)
                villo

                sorry to pull this up...
                I've been struggling for a while on a similar problem, and I would like to figure out how seam context variables work.

                I can get the above working, given that the items come from a seam component, i.e declared with @Name.

                But I can't get the following working

                <h:dataTable var="section" value="#{component.list}">
                 <h:column>
                 <c:forEach var="item" items="#{section.item}">
                 <h:inputText value="#{item.text}"/>
                 </c:forEach>
                 </h:column>
                </h:dataTable>
                


                where template is a seam component, with a @Datamodel section.
                In this case the forEach is just ignored...

                I would apreciate if someone could shed some light on this,
                cheers
                Francesco

                • 5. Re: Strange behavior using JSTL (MyFaces)
                  pmuir

                  The <c:forEach> is evaluated at compile-time, the <h:dataTable> is evaluated at render-time. This means that the section variable is not available at compile-time to the <c:forEach>.

                  So you could change your <h:dataTable> to be another <c:forEach> (using a list to back it), or, if you use facelets, you could use the <ui:repeat> component which is a render-time equivalent of c:forEach. The facelets option is better as it is lighter weight.

                  • 6. Re: Strange behavior using JSTL (MyFaces)
                    gavin.king

                    I think if you use facelets, there is no compile-time evaluation, so stuff Just Works.

                    • 7. Re: Strange behavior using JSTL (MyFaces)
                      pmuir

                      In facelets c:forEach is evaluated at compile time (afaik, see http://wiki.java.net/bin/view/Projects/FaceletsFAQ#What_s_the_difference_between_c but as I mentioned you can use ui:repeat as a render-time replacement.

                      • 8. Re: Strange behavior using JSTL (MyFaces)
                        villo

                        Thanks petemuir. using forEach works:)

                        I still don't have clear the reason BTW...
                        Does this has anything to do with the following?
                        http://java.sun.com/products/jsp/reference/techart/unifiedEL.html

                        In the dvd store example jstl tests access components' methods, while I was trying to use elements of a datamodel. This is the only difference I can see; I'm not sure of it at all but it makes sense to think that the <h:dataTable> element and the <c:forEach> are evaluated at different times...

                        Is there any document out there describing when components and context variables are used in the different JSF phases?

                        cheers
                        Francesco

                        • 9. Re: Strange behavior using JSTL (MyFaces)
                          pmuir

                          As I understand it (this is quite likely to be a facelets centric view ;) )

                          // Your code
                          ...
                           <h:dataTable value="#{dataModel}" var="row">
                           <h:column>#{row.col1}</h:column>
                           <h:column>#{row.col2}</h:column>
                           </h:dataTable>
                          
                           <c:forEach items="#{list}" var="row">
                           #{row.col1} #{row.col2}
                           </c:forEach>
                          ...
                          


                          When the component tree is created (compile-time) components like dataTable are added to the tree without the backing list being read (i.e. a single instance) whilst forEach's backing list is evaluated (so if there are x items in the c:forEach list then x copies of forEach's children would be added).

                          i.e.

                          // After tree compile - pseudo-code (if list has 3 items)
                          ...
                           <h:dataTable value="#{dataModel}" var="row">
                           <h:column>#{row.col1}</h:column>
                           <h:column>#{row.col2}</h:column>
                           </h:dataTable>
                          
                           #{row1.col1} #{row1.col2}
                           #{row2.col1} #{row2.col2}
                           #{row3.col1} #{row3.col2}
                          ...
                          




                          When the tree is rendered dataTable's DataModel is read and a row for each item in the list is written.

                          
                          // After tree render - pseudo-code (if dataModel has 3 items)
                          ...
                           <h:column>#{row1.col1}</h:column><h:column>#{row1.col2}</h:column>
                           <h:column>#{row2.col1}</h:column><h:column>#{row2.col2}</h:column>
                           <h:column>#{row3.col1}</h:column><h:column>#{row3.col2}</h:column>
                          
                           #{row1.col1} #{row1.col2}
                           #{row2.col1} #{row2.col2}
                           #{row3.col1} #{row3.col2}
                          ...
                          


                          In essence the component tree will hold an item per child of forEach and an item per dataTable - hence why dataTable is a lighter weight pattern.

                          It didn't work for you as the dataTable's is evaluated AFTER forEach - so the 'var' items of dataTable aren't created when forEach is evaluated ;)

                          Peter

                          • 10. Re: Strange behavior using JSTL (MyFaces)
                            pmuir

                            Oh, and JSF 1.1doesn't use unified EL (as mentioned in your link).

                            • 11. Re: Strange behavior using JSTL (MyFaces)
                              villo


                              thanks for the answer, I finally have it clear!
                              cheers
                              Freancesco