Sealyu

          --- 博客已遷移至: http://www.sealyu.com/blog

            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
            618 隨筆 :: 87 文章 :: 225 評論 :: 0 Trackbacks

          How to iterate over java.util.Set in JSF

          By bozhobg

          I spent quite some time trying to find a solution for the following JSF issue: it is not possible to iterate over a java.util.Set.
          - ui:repeat (facelets) doesn’t work
          - a4j:repeat (richfaces) doesn’t work
          - c:forEach works..only in case it does not rely on a variable defined by a parent component (rich:dataTable for instance)

          All above are pretty logical phenomena, as UIData relies on ordered data, and generally a Set is not ordered.

          In my case I had to use a Set defined in the Hibernate (JPA) object (PersistentSet).
          An important note: you should use a set in case the view order is of no matter to you.

          The solution..is pretty simple. And I’ll suggest it to be a part of facelets/richfaces for the next version, unless of course there is some valid specific

          reason for it not to be.

          1. Define your own UI component extending an existing repeater component. I used a4j:repeat (HtmlAjaxRepeat)
          2. Override the metohd getDataModel
          3. Define your component in your faces-config
          4. create a custom facelets tag definition
          5. Define a context-variable in web.xml pointing to the facelet tag definition.

          Note: for use with JSP instead of Facelets, you should define a .tld and a Tag handler, which is not an ojbect of this post.

          Now let’s see the steps in detail:

          1,2. Here some code:

          1. package com.myproject.components;  
          2. import java.util.ArrayList;  
          3. import java.util.Set;  
          4.   
          5. import javax.faces.model.DataModel;  
          6. import javax.faces.model.ListDataModel;  
          7.   
          8. import org.ajax4jsf.component.html.HtmlAjaxRepeat;  
          9. import org.ajax4jsf.model.SequenceDataModel;  
          10.   
          11. public class UIIterator extends HtmlAjaxRepeat {  
          12.   
          13.    @SuppressWarnings("unchecked")  
          14.    @Override  
          15.    protected DataModel getDataModel() {  
          16.       Object current = getValue();  
          17.       if(current instanceof Set){  
          18.           return new SequenceDataModel(new ListDataModel(  
          19.                 new ArrayList((Set) current)));  
          20.       }  
          21.       return super.getDataModel();  
          22.    }  
          23. }  

          So, as we don’t care about the order of the elements, we just create a new ArrayList out of the Set. And we can now easily return the appropirate DataModel.

          3. Add this to your faces-config. (I copied it from the a4j definition)

          1. <component>  
          2.         <description />  
          3.         <display-name>Iterator</display-name>  
          4.         <component-type>com.myproject.Iterator</component-type>  
          5.         <component-class>com.myproject.components.UIIterator</component-class>  
          6.   
          7.         <component-extension>  
          8.             <component-family>javax.faces.Data</component-family>  
          9.             <renderer-type>org.ajax4jsf.components.RepeatRenderera</renderer-type>  
          10.         </component-extension>  
          11.     </component>  

          4. Here is the tag definition for facelets

          1. <?xml version="1.0" encoding="UTF-8"?>  
          2. <!DOCTYPE facelet-taglib PUBLIC  
          3. "-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN"  
          4. "http://java.sun.com/dtd/facelet-taglib_1_0.dtd">  
          5. <facelet-taglib xmlns="http://java.sun.com/JSF/Facelet">  
          6. <namespace>http://myproject.com/cust</namespace>  
          7.   
          8. <tag>  
          9. <tag-name>repeat</tag-name>  
          10. <component>  
          11. <component-type>com.myproject.Iterator</component-type>  
          12. <renderer-type>org.ajax4jsf.components.RepeatRenderer</renderer-type>  
          13. </component>  
          14. </tag>  
          15.   
          16. </facelet-taglib>  

          Save this file as /WEB-INF/facelets/custom.taglib.xml

          5. Add to your web.xml

          1. <context-param>  
          2. <param-name>facelets.LIBRARIES</param-name>  
          3. <param-value>/WEB-INF/facelets/custom.taglib.xml</param-value>  
          4. </context-param>  

          6. It is now ready to use

          xmlns:cust=”http://myproject.com/cust”

          <cust:repeat var=”myVar” value=”${aSet}”>

          </cust:repeat>
          I think it is way neater than other workarounds, like defining a custom EL Resolver.


          posted on 2009-04-01 13:47 seal 閱讀(826) 評論(0)  編輯  收藏 所屬分類: Seam
          主站蜘蛛池模板: 共和县| 车险| 福清市| 南雄市| 贵州省| 大丰市| 阿合奇县| 米林县| 阳泉市| 乡宁县| 宝清县| 祁阳县| 滨州市| 丽江市| 龙陵县| 聊城市| 扎兰屯市| 玉龙| 孟村| 岐山县| 巫山县| 长丰县| 平凉市| 西安市| 广德县| 乐至县| 阜新市| 眉山市| 新沂市| 武汉市| 丹凤县| 克什克腾旗| 根河市| 梧州市| 高尔夫| 枣阳市| 景洪市| 中江县| 始兴县| 建昌县| 温泉县|