??xml version="1.0" encoding="utf-8" standalone="yes"?>91九色在线观看,羞羞色午夜精品一区二区三区,亚洲女优视频http://www.aygfsteel.com/sealyu/category/37289.html--- The devil's in the Detailszh-cnThu, 10 Jun 2010 17:02:59 GMTThu, 10 Jun 2010 17:02:59 GMT60Setting the conversation-timeout in Seam, why it really does workhttp://www.aygfsteel.com/sealyu/archive/2010/04/20/318792.htmlsealsealMon, 19 Apr 2010 16:36:00 GMThttp://www.aygfsteel.com/sealyu/archive/2010/04/20/318792.htmlhttp://www.aygfsteel.com/sealyu/comments/318792.htmlhttp://www.aygfsteel.com/sealyu/archive/2010/04/20/318792.html#Feedback0http://www.aygfsteel.com/sealyu/comments/commentRss/318792.htmlhttp://www.aygfsteel.com/sealyu/services/trackbacks/318792.htmlConversation timeout seems to be a commonly misunderstood Seam concept. I often see postings on the Seam forums claiming that the conversation-timeout doesn’t work! Well, actually it does, you simply have to understand the semantics.

Configuring the conversation-timeout period can be accomplished through the following in your components.xml:

<core:manager conversation-timeout="900000" />

At first glance most developers relate conversation-timeout to session timeout, where any conversation will simply timeout after the configured conversation timeout period. As you will quickly notice during testing, this is not the case. To execute a quick experiment, try the following configuration in the components.xml of the seam-booking example:

<core:manager conversation-timeout="60000" />

Because the conversation-timeout is set in milliseconds, the above configuration sets the conversation-timeout to 1 minute. Now in the web.xml set the session timeout to 5 minutes:

<session-config>
<session-timeout>5</session-timeout>
</session-config>

Now in the destroy method of the HotelBookingAction add the following line:

...
@Destroy @Remove
public void destroy() {
log.info("Destroying HotelBookingAction...");
}
...

This will log our message when the conversation ends and the HotelBookingAction is destroyed. Now deploy the seam-booking example to your local JBoss instance and start up a conversation. This can be accomplished by logging in, navigating to the hotels listing, and selecting a hotel for booking. At this point, wait for the 1 minute period… nothing happens. Now wait for another 4 minutes, the message is displayed. The conversation timed out along with the session.

Foreground vs. Background Conversations

So why didn’t our conversation timeout as configured? This is because the conversation-timeout only affects background conversations. The foreground conversation will only timeout when the session times out. Foreground, background, what? The foreground conversation is the conversation that the user last interacted with. A background conversation is any other conversation in the user’s session. Thus, in our previous scenario the foreground conversation timed out with the session as expected.

Now lets try another approach. Perform the same steps as before to proceed to the booking screen. Now open a new window and perform the same steps. We now have a foreground conversation and a background conversation in progress. Again, wait 1 minute. Nothing happened. If you wait an additional 4 minutes, both conversations will timeout. So what is going on here, I thought we had a background conversation? We did, Seam simply checks the conversation timeout on each request. Thus, if I interact with the foreground conversation after 1 minute, the background conversation times out. Try it, perform the same steps, wait 1 minute and then click on the window of the foreground conversation and you will see the log message.

This is very desirable behavior. Essentially when a user leaves his or her desk for a period of time and comes back, if the session is still active it would be desirable to maintain the state the user was previously in. This is the foreground conversation state. All other background conversation state is left to timeout after the configured conversation-timeout period which reduces overall memory consumption. This enables a developer to think less about memory usage and cleaning up state and more about developing business logic. That’s why we’re here right?

Letting the user choose

So you may be asking at this point why the conversation-timeout doesn’t use polling. As we said, you must interact with the foreground conversation to cause the background conversations to timeout after the conversation-timeout period. Imagine that the user had many windows open and leaves his or her desk. Based on which window the user clicks on when they return, that becomes the foreground conversation timing out any other background conversations. This gives the user a chance to resume whichever conversation he or she chooses, not the one the developer chooses.



seal 2010-04-20 00:36 发表评论
]]>
javascript CDATA的意?http://www.aygfsteel.com/sealyu/archive/2009/12/07/304961.htmlsealsealMon, 07 Dec 2009 02:04:00 GMThttp://www.aygfsteel.com/sealyu/archive/2009/12/07/304961.htmlhttp://www.aygfsteel.com/sealyu/comments/304961.htmlhttp://www.aygfsteel.com/sealyu/archive/2009/12/07/304961.html#Feedback0http://www.aygfsteel.com/sealyu/comments/commentRss/304961.htmlhttp://www.aygfsteel.com/sealyu/services/trackbacks/304961.htmlCDATA 内部的所有东襉K会被解析器忽略?/p>

假如文本中包含了大量?"<" ?"&" 字符 - 像~程代码中经常出现的情况一?- 那么q个 XML 元素可以被定义Z?CDATA 部分?/p>

CDATA 区段开始于 "<![CDATA["Q结束于 "]]>"Q?/p>

<script type="text/javascript">
<![CDATA[
function compare(a,b)
{
if (a < b)
   {alert("a于b");}
else if (a>b)
   {alert("a大于b");}
else
   {alert("a{于b");}
}
]]>
</script>

在上面的例子中,?CDATA 区段中的所有东襉K会被解析器忽略?/p>


关于 CDATA 区段的注?

CDATA 区段不能包含字符?"]]>"Q所以,CDATA 区段的嵌套是不被允许的?/p>

同时也需要确保在 "]]>" 字符串中没有I格或折行?/p>

Z么要使用CDATA:

       XHTML的第二个改变是用CDATADcXML中的CDATAD는于声明不应被解析为标{文本QXHTML也是如此Q,q样可以用特D字W,? 于Q?lt;Q、大于(>Q、和P&Q和双引P"Q,而不必用它们的字符实体。考虑下面的代码:

<script type="text/javascript">
function compare(a,b)
{
if (a < b)
   {alert("a于b");}
else if (a>b)
   {alert("a大于b");}
else
   {alert("a{于b");}
}
</script>

q个函数相当单,它比较数字a和bQ然后显C消息说明它们的关系。但是,在XHTML中,q段代码是无效的Q因为它使用了三个特D符P卛_于? 大于和双引号。要修正q个问题Q必d别用q三个字W的XML实体&lt;?amp;gt;?amp;quot;替换它们Q?/p>

<script type="text/javascript">
function compare(a,b)
{
if (a &lt;b)
   {alert(&quot;a于b&quot;);}  
else if (a&gt;b)
   {alert(&quot;a大于b&quot;);}
else
   {alert(&quot;a{于b&quot;);}
}
</script>

q段代码存在两个问题。首先,开发者不习惯用XML实体~写代码。这使代码很难读懂。其ơ,在JavaScript中,q种代码实际上将视ؓ有语? 错,因ؓ解释E序不知道XML实体的意思。用CDATAD即可以以常规Ş式(xȝ语法Q编写JavaScript代码。正式加入CDATAD늚Ҏ? 下:

<script type="text/javascript">
<![CDATA[
function compare(a,b)
{
if (a < b)
   {alert("a于b");}
else if (a>b)
   {alert("a大于b");}
else
   {alert("a{于b");}
}
]]>
</script>

虽然q是正式方式Q但q要CQ大多数览器都不完全支持XHTMLQ这带来主要问题,卌在JavaScript中是个语法错误,因ؓ大多数浏览器q不认识CDATADc?/p>

<script type="text/javascript">
//<![CDATA[                                            
function compare(a,b)
{
if (a < b)
   {alert("a于b");}
else if (a>b)
   {alert("a大于b");}
else
   {alert("a{于b");}
}
//]]>                                      
</script>

当前使用的解x案模仿了“Ҏ览器隐?#8221;代码的方法。用单行的JavaScript注释"http://"Q可在不影响代码语法的情况下嵌入CDATAD:

现在Q这D代码在不支持XHTML的浏览器中也可运行?/p>

但是Qؓ避免CDATA的问题,最好还是用外部文g引入JavaScript代码?/p>

seal 2009-12-07 10:04 发表评论
]]>
richfaces 的脚本冲H问题(prototype.jsQ?/title><link>http://www.aygfsteel.com/sealyu/archive/2009/10/28/300003.html</link><dc:creator>seal</dc:creator><author>seal</author><pubDate>Wed, 28 Oct 2009 00:11:00 GMT</pubDate><guid>http://www.aygfsteel.com/sealyu/archive/2009/10/28/300003.html</guid><wfw:comment>http://www.aygfsteel.com/sealyu/comments/300003.html</wfw:comment><comments>http://www.aygfsteel.com/sealyu/archive/2009/10/28/300003.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/sealyu/comments/commentRss/300003.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/sealyu/services/trackbacks/300003.html</trackback:ping><description><![CDATA[在页面中使用了richfaces和prototypeQ结果在IE下一直报错,后来发现richfaces的文档中已经标注了此问题Q?br /> <div> <div> <div> <div> <h2><a id="d0e1572">1.74. Why does Java Script conflict?</a></h2> </div> </div> </div> <p><a id="d0e1572">Richfaces 3.1.3 uses 1.6.0 version of prototype.js script instead of 1.5.1 that's been used for earlier versions. There are 2 prototype versions included (the first included implicitly as a dependency of toggle panel components and the second one included explicitly as a link). Versions conflict is the cause of the problem.</a></p> <p><a id="d0e1572">RichFaces 3.1.3 is bundled with the same ones as Prototype 1.6.0, Scriptaculous 1.8.0</a></p> <p> <a id="d0e1572"> <strong>Example in web.xml::</strong> </a></p> <pre xmlns="" xmlns:rf="java:org.jboss.highlight.XhtmlRendererFactory" class="XML"><br /> <a id="d0e1572">...</a><a id="d0e1572"><br /> <br /> <context-param><br /> <br />     <param-name>org.richfaces.ExcludeScripts</param-name><br /> <br />     <param-value>Prototype,Scriptaculous</param-value><br /> <br /> </context-param><br /> <br /> ...<br /> <br /> </a></pre> <p><a id="d0e1572">RichFaces components use Prototype very hard. In particular, some patches has been removed that are already included into 1.6.0. Adding feature with exclusion makes it possible to use Prototype with version less than 1.6.0. This will break some of the components.</a></p> </div> <br /> <br /> <img src ="http://www.aygfsteel.com/sealyu/aggbug/300003.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/sealyu/" target="_blank">seal</a> 2009-10-28 08:11 <a href="http://www.aygfsteel.com/sealyu/archive/2009/10/28/300003.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Seam扩展事务消息http://www.aygfsteel.com/sealyu/archive/2009/10/23/299454.htmlsealsealFri, 23 Oct 2009 02:40:00 GMThttp://www.aygfsteel.com/sealyu/archive/2009/10/23/299454.htmlhttp://www.aygfsteel.com/sealyu/comments/299454.htmlhttp://www.aygfsteel.com/sealyu/archive/2009/10/23/299454.html#Feedback0http://www.aygfsteel.com/sealyu/comments/commentRss/299454.htmlhttp://www.aygfsteel.com/sealyu/services/trackbacks/299454.html 当事务成功之后(调用 persist()?tt>update() ?remove() 成功后)QHome对象会发Z?org.jboss.seam.afterTransactionSuccess 事g? 通过监听q一事gQ我们可以在底层实体改变后,h查询? 如果我们只需要在特定的实体保存、修Ҏ删除后刷新特定查询,我们可以监视 org.jboss.seam.afterTransactionSuccess.<name> 事gQ?tt><name> 是实体的名字Q?

当一个操作成功时QHome对象可以自动地显CFaces信息Q我们可以再一ơ通过配置来定制信息?

<factory name="person"
value="#{personHome.instance}"/>

<framework:entity-home name="personHome"
entity-class="eg.Person"
new-instance="#{newPerson}">
<framework:created-message>New person #{person.firstName} #{person.lastName} created</framework:created-message>
<framework:deleted-message>Person #{person.firstName} #{person.lastName} deleted</framework:deleted-message>
<framework:updated-message>Person #{person.firstName} #{person.lastName} updated</framework:updated-message>
</framework:entity-home>

<component name="newPerson"
class="eg.Person">
<property name="nationality">#{country}</property>
</component>

或者扩展:

@Name("personHome")
public class PersonHome extends EntityHome<Person> {

@In Country country;

@Factory("person")
public Person initPerson() { return getInstance(); }

protected Person createInstance() {
return new Person(country);
}

protected String getCreatedMessage() { return "New person #{person.firstName} #{person.lastName} created"; }
protected String getUpdatedMessage() { return "Person #{person.firstName} #{person.lastName} updated"; }
protected String getDeletedMessage() { return "Person #{person.firstName} #{person.lastName} deleted"; }

}

但是指定信息最好的Ҏ是把信息|于Seam所知的resource bundle中(在默认情况下Q这个bundle叫做 messages Q?

Person_created=New person #{person.firstName} #{person.lastName} created
Person_deleted=Person #{person.firstName} #{person.lastName} deleted
Person_updated=Person #{person.firstName} #{person.lastName} updated

q样方便q行国际化,从表现层的角度考虑也保持了代码和配|的整洁?

最后一步是使用 <s:validateAll> ?<s:decorate> 向页面中d验证功能Q我会把q个留给你们自己d现?



seal 2009-10-23 10:40 发表评论
]]>
解决Safari中Richfaces某些lg不兼容的问题http://www.aygfsteel.com/sealyu/archive/2009/09/22/295950.htmlsealsealTue, 22 Sep 2009 01:56:00 GMThttp://www.aygfsteel.com/sealyu/archive/2009/09/22/295950.htmlhttp://www.aygfsteel.com/sealyu/comments/295950.htmlhttp://www.aygfsteel.com/sealyu/archive/2009/09/22/295950.html#Feedback0http://www.aygfsteel.com/sealyu/comments/commentRss/295950.htmlhttp://www.aygfsteel.com/sealyu/services/trackbacks/295950.html 感觉无从查vQ只能借助Google?br /> 才发现原来Safari下很多Richfaces的组仉会出现问题,解决Ҏ反而很单:
在你的xhtml面Q或者你用jsp或其他模板技术)的页首位|,加这行:
<f:view contentType="text/html" />

问题解决?/pre>



seal 2009-09-22 09:56 发表评论
]]>Seam中简单的checkbox操作http://www.aygfsteel.com/sealyu/archive/2009/09/02/293563.htmlsealsealWed, 02 Sep 2009 03:26:00 GMThttp://www.aygfsteel.com/sealyu/archive/2009/09/02/293563.htmlhttp://www.aygfsteel.com/sealyu/comments/293563.htmlhttp://www.aygfsteel.com/sealyu/archive/2009/09/02/293563.html#Feedback0http://www.aygfsteel.com/sealyu/comments/commentRss/293563.htmlhttp://www.aygfsteel.com/sealyu/services/trackbacks/293563.html 在用Seam和Richfaces开发的时候,一个简单的a4j:support ?reRender q不能解决问题。试验了一番,解决了这个问题,例子代码Q?br />
 1 <h:selectBooleanCheckbox value="#{beanA.propertyA}"
 2     styleClass="check" onclick="showHideHistorySelector()" id="adminView"/>
 3 <s:div id="historySelectorRegion">
 4     <h:panelGrid columns="3" rendered="#{beanA.propertyA}">
 5         //Content here
 6     </h:panelGrid>
 7 </s:div>
 8 <a4j:jsFunction name="showHideHistorySelector" status="waitingMask"
 9     reRender="historySelectorRegion" ajaxSingle="true"
10     process="adminView" action="#"/>

通过使用a4j:jsFunction的process属性来控制可以解决问题?br />

seal 2009-09-02 11:26 发表评论
]]>
Seam中在java文g中用资源文?/title><link>http://www.aygfsteel.com/sealyu/archive/2009/09/01/293425.html</link><dc:creator>seal</dc:creator><author>seal</author><pubDate>Tue, 01 Sep 2009 03:41:00 GMT</pubDate><guid>http://www.aygfsteel.com/sealyu/archive/2009/09/01/293425.html</guid><wfw:comment>http://www.aygfsteel.com/sealyu/comments/293425.html</wfw:comment><comments>http://www.aygfsteel.com/sealyu/archive/2009/09/01/293425.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/sealyu/comments/commentRss/293425.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/sealyu/services/trackbacks/293425.html</trackback:ping><description><![CDATA[在java 中如果想从国际化资源文g中读取文本,可以通过注入seam的一个组Ӟ<br /> @In(value="org.jboss.seam.international.messages")<br />     private Map<String, String> messages;<br /> <br /> 在用时Q只需要像下面q样Q?br /> String abc = messages.get("person.name.required");<br /> <img src ="http://www.aygfsteel.com/sealyu/aggbug/293425.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/sealyu/" target="_blank">seal</a> 2009-09-01 11:41 <a href="http://www.aygfsteel.com/sealyu/archive/2009/09/01/293425.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Seam 目部v?tomcat ??http://www.aygfsteel.com/sealyu/archive/2009/08/26/292632.htmlsealsealWed, 26 Aug 2009 04:36:00 GMThttp://www.aygfsteel.com/sealyu/archive/2009/08/26/292632.htmlhttp://www.aygfsteel.com/sealyu/comments/292632.htmlhttp://www.aygfsteel.com/sealyu/archive/2009/08/26/292632.html#Feedback0http://www.aygfsteel.com/sealyu/comments/commentRss/292632.htmlhttp://www.aygfsteel.com/sealyu/services/trackbacks/292632.html JBoss Tools 生成?nbsp;Seam 目Q新建项目时Q服务器选择 tomcatQ,会生成一些必要的文gQ如Q连接数据库的数据源文gQ如Q?/font>project-ds.xml Q但它只能在 Jboss as 的环境中q行Q不适用?nbsp;tomcatQ,要想很我们的目Q?/font>warQ运行于 tomcat 中的Q我们得对它自动生成的文件做一些必要的修改?/font>

      一?span style="font-weight: normal; font-size: 10.5pt; font-family: '宋体';">修改数据库的q接方式

         1、采用数据源的Ş?br />             ?nbsp;tomcat 中配|数据源方式如下:
            
在生成的目同目录中找此文Ӟ context.xml 
                     
Servers/Tomcat 。。?/font>/context.xml  作如下配|:
            
在标{?nbsp;<Context> 中间加入:
            <Resource  
                  
name="jdbc/demo" auth="Container" type="javax.sql.DataSource" 
                  
maxActive="30" maxIdle="5" maxWait="10000" username="root" 
                  
password="admindriverClassName="com.mysql.jdbc.Driver" 
                  
url="jdbc:mysql://localhost:3306/demo?useUnicode=true&amp;characterEncoding=UTF-8">

          </Resource>          

         2?span style="font-weight: normal; font-size: 10.5pt; font-family: '宋体';">使用非数据源的Ş?br />             在文Ӟpersistence.xml 中添?/font>hibernate 的连接数据库的方式,如下Q?br />               <property name="hibernate.connection.username" value="root"/>
            
<property name="hibernate.connection.password" value="admin"/>
            
<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
            <property name="hibernate.connection.url" 
                  
value="jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=UTF-8"/>

      二?span style="font-weight: normal; font-size: 10.5pt; font-family: '宋体';">修改 JPA 配置文g persistence.xml

          1?/span>如果数据的连接方式采用数据源的Ş式,则只需修改里面数据源的名称Q如Q?br />             <jta-data-source>java:comp/env/jdbc/demo</jta-data-source>

          2、如果采?font face="Times New Roman">hibernate 的连接方式,则把此行删了?/font>        

          3?span style="font-weight: normal; font-size: 10.5pt; font-family: '宋体';">删除里面的此行配|:
             <property name="hibernate.transaction.manager_lookup_class" 
                  value="org.hibernate.transaction.JBossTransactionManagerLookup"/>

          4、修改事务的{略方式?RESOURCE_LOCAL Q?nbsp;

            <persistence-unit name="demo" transaction-type="RESOURCE_LOCAL">

      三?span style="font-weight: normal; font-size: 10.5pt; font-family: '宋体';">配置 Seam 的事务管理器
          ?nbsp;component.xml 文g加入Q?br />           <transaction:entity-transaction entity-manager="#{entityManager}"/>
         默认生成的此文g是不含有 transaction 的命名空_需要手动在此文件加入它的命名空_

          xmlns:transaction=http://jboss.com/products/seam/transaction
         http://jboss.com/products/seam/transaction 
         http://jboss.com/products/seam/transaction-2.1.xsd

      四?span style="font-weight: normal; font-size: 10.5pt; font-family: '宋体';">为此目加入必要的依赖包 。。。。。?/span>



seal 2009-08-26 12:36 发表评论
]]>
rich:tree中drag和drop后reRender对应的treehttp://www.aygfsteel.com/sealyu/archive/2009/08/13/291006.htmlsealsealThu, 13 Aug 2009 07:05:00 GMThttp://www.aygfsteel.com/sealyu/archive/2009/08/13/291006.htmlhttp://www.aygfsteel.com/sealyu/comments/291006.htmlhttp://www.aygfsteel.com/sealyu/archive/2009/08/13/291006.html#Feedback0http://www.aygfsteel.com/sealyu/comments/commentRss/291006.htmlhttp://www.aygfsteel.com/sealyu/services/trackbacks/291006.html 在DropEvent对应的listener的方法中可以调用AjaxContext重新reRenderQ?br /> public void processDrop(DropEvent dropEvent){
。。?br /> ?/此处处理逻辑
UITreeNode destNode = (UITreeNode)dropEvent.getSource();
AjaxContext ac = AjaxContext.getCurrentInstance();
// Add destination tree to reRender
 ac.addComponentToAjaxRender(destNode.getUITree());

另外Q如果要在拖拽后reRender其他的节点,要用到oncomplete属性,使用一个jsfunction来reRender。单U的reRender不v作用Q我猜原因可能是listenerq不是按照一个ajaxh的方式来的,所以单U的ajax reRender也不起作用?br />



seal 2009-08-13 15:05 发表评论
]]>
SEAM的PAGE和CONVERSATION contexthttp://www.aygfsteel.com/sealyu/archive/2009/08/13/291001.htmlsealsealThu, 13 Aug 2009 06:53:00 GMThttp://www.aygfsteel.com/sealyu/archive/2009/08/13/291001.htmlhttp://www.aygfsteel.com/sealyu/comments/291001.htmlhttp://www.aygfsteel.com/sealyu/archive/2009/08/13/291001.html#Feedback0http://www.aygfsteel.com/sealyu/comments/commentRss/291001.htmlhttp://www.aygfsteel.com/sealyu/services/trackbacks/291001.html 如果在一个页面中保持状? 优先使用PAGE context,q样可以提高效率.



seal 2009-08-13 14:53 发表评论
]]>
rich:tree ?adviseNodeOpened ?adviseNodeSelected属?/title><link>http://www.aygfsteel.com/sealyu/archive/2009/08/13/291000.html</link><dc:creator>seal</dc:creator><author>seal</author><pubDate>Thu, 13 Aug 2009 06:51:00 GMT</pubDate><guid>http://www.aygfsteel.com/sealyu/archive/2009/08/13/291000.html</guid><wfw:comment>http://www.aygfsteel.com/sealyu/comments/291000.html</wfw:comment><comments>http://www.aygfsteel.com/sealyu/archive/2009/08/13/291000.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/sealyu/comments/commentRss/291000.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/sealyu/services/trackbacks/291000.html</trackback:ping><description><![CDATA[在rich:tree中如果想要在面中初始化tree的展开和选中状态或者在面更改后返回时保持之前的状态,<br /> 可以讄tree的adviseNodeOpened ?adviseNodeSelected属性?br /> <table xmlns:javaee="http://java.sun.com/xml/ns/javaee" xmlns:fo="http://www.w3.org/1999/XSL/Format" cellpadding="3" cellspacing="0" width="100%"> <tbody> <tr valign="top"> <td>adviseNodeOpened</td> <td>false</td> <td>false</td> <td> <code>javax.el.MethodExpression</code> <br /> (<em>signature must match </em> <code>java.lang.Boolean adviseNodeOpened(org.richfaces.component.UITree)</code>) </td> <td>MethodBinding pointing at a method accepting an org.richfaces.component.UITree with return of java.lang.Boolean type. If returned value is: java.lang.Boolean. TRUE, a particular treeNode is expanded; java.lang.Boolean.FALSE, a particular treeNode is collapsed; null, a particular treeNode saves the current state</td> </tr> <tr valign="top"> <td>adviseNodeSelected</td> <td>false</td> <td>false</td> <td> <code>javax.el.MethodExpression</code> <br /> (<em>signature must match </em> <code>java.lang.Boolean adviseNodeSelected(org.richfaces.component.UITree)</code>) </td> <td>MethodBinding pointing at a method accepting an org.richfaces.component.UITree with return of java.lang.Boolean type. If returned value is: java.lang.Boolean. TRUE, a particular treeNode is selected; java.lang.Boolean.FALSE, a particular treeNode is unselected; null, a particular treeNode saves the current state</td> </tr> </tbody> </table> <br /> <br /> <img src ="http://www.aygfsteel.com/sealyu/aggbug/291000.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/sealyu/" target="_blank">seal</a> 2009-08-13 14:51 <a href="http://www.aygfsteel.com/sealyu/archive/2009/08/13/291000.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Concurrent calls to conversational componentshttp://www.aygfsteel.com/sealyu/archive/2009/07/20/287417.htmlsealsealMon, 20 Jul 2009 02:17:00 GMThttp://www.aygfsteel.com/sealyu/archive/2009/07/20/287417.htmlhttp://www.aygfsteel.com/sealyu/comments/287417.htmlhttp://www.aygfsteel.com/sealyu/archive/2009/07/20/287417.html#Feedback0http://www.aygfsteel.com/sealyu/comments/commentRss/287417.htmlhttp://www.aygfsteel.com/sealyu/services/trackbacks/287417.html A general discussion of concurrent calls to Seam components can be found in Section 4.1.10, “Concurrency model”. Here we will discuss the most common situation in which you will encounter concurrency ?accessing conversational components from AJAX requests. We're going to discuss the options that a Ajax client library should provide to control events originating at the client ?and we'll look at the options RichFaces gives you.

Conversational components don't allow real concurrent access therefore Seam queues each request to process them serially. This allows each request to be executed in a deterministic fashion. However, a simple queue isn't that great ?firstly, if a method is, for some reason, taking a very long time to complete, running it over and over again whenever the client generates a request is bad idea (potential for Denial of Service attacks), and, secondly, AJAX is often to used to provide a quick status update to the user, so continuing to run the action after a long time isn't useful.

Therefore, when you are working inside a long running conversation, Seam queues the action event for a period of time (the concurrent request timeout); if it can't process the event in time, it creates a temporary conversation and prints out a message to the user to let them know what's going on. It's therefore very important not to flood the server with AJAX events!

We can set a sensible default for the concurrent request timeout (in ms) in components.xml:


<core:manager concurrent-request-timeout="500" />

We can also fine tune the concurrent request timeout on a page-by-page basis:


<page view-id="/book.xhtml" 

         conversation-required="true" 

         login-required="true"

         concurrent-request-timeout="2000" />

So far we've discussed AJAX requests which appear serial to the user - the client tells the server that an event has occur, and then rerenders part of the page based on the result. This approach is great when the AJAX request is lightweight (the methods called are simple e.g. calculating the sum of a column of numbers). But what if we need to do a complex computation thats going to take a minute?

For heavy computation we should use a poll based approach ?the client sends an AJAX request to the server, which causes action to be executed asynchronously on the server (the response to the client is immediate) and the client then polls the server for updates. This is good approach when you have a long-running action for which it is important that every action executes (you don't want some to timeout).

Well first, you need to decide whether you want to use the simpler "serial" request or whether you want to use a polling approach.

If you go for a "serial" requests, then you need to estimate how long your request will take to complete - is it much shorter than the concurrent request timeout? If not, you probably want to alter the concurrent request timeout for this page (as discussed above). You probably want a queue on the client side to prevent flooding the server with requests. If the event occurs often (e.g. a keypress, onblur of input fields) and immediate update of the client is not a priority you should set a request delay on the client side. When working out your request delay, factor in that the event may also be queued on the server side.

Finally, the client library may provide an option to abort unfinished duplicate requests in favor of the most recent.

Using a poll-style design requires less fine-tuning. You just mark your action method @Asynchronous and decide on a polling interval:


}

However carefully you design your application to queue concurrent requests to your conversational component, there is a risk that the server will become overloaded and be unable to process all the requests before the request will have to wait longer than the concurrent-request-timeout. In this case Seam will throw a ConcurrentRequestTimeoutException which can be handled in pages.xml. We recommend sending an HTTP 503 error:


   <exception class="org.jboss.seam.ConcurrentRequestTimeoutException" logLevel="trace">

      <http-error error-code="503" />

   </exception>

Alternatively you could redirect to an error page:


<exception class="org.jboss.seam.ConcurrentRequestTimeoutException" logLevel="trace">

   <end-conversation/>

   <redirect view-id="/error.xhtml">

      <message>The server is too busy to process your request, please try again later</message>

   </redirect>

</exception>

ICEfaces, RichFaces Ajax and Seam Remoting can all handle HTTP error codes. Seam Remoting will pop up a dialog box showing the HTTP error and ICEfaces will indicate the error in it's connection status component. RichFaces Ajax provides the most complete support for handling HTTP errors by providing a user definable callback. For example, to show the error message to the user:

<script type="text/javascript">
A4J.AJAX.onError = function(req,status,message) {
alert("message");
};
</script>

RichFaces Ajax is the AJAX library most commonly used with Seam, and provides all the controls discussed above:



seal 2009-07-20 10:17 发表评论
]]>
又一个有点变态的Seam错误Q?Property ‘xxx?not readable on type java.lang.Boolean http://www.aygfsteel.com/sealyu/archive/2009/07/20/287397.htmlsealsealMon, 20 Jul 2009 01:24:00 GMThttp://www.aygfsteel.com/sealyu/archive/2009/07/20/287397.htmlhttp://www.aygfsteel.com/sealyu/comments/287397.htmlhttp://www.aygfsteel.com/sealyu/archive/2009/07/20/287397.html#Feedback0http://www.aygfsteel.com/sealyu/comments/commentRss/287397.htmlhttp://www.aygfsteel.com/sealyu/services/trackbacks/287397.html 错误如下Q?br /> 在用rich:inplaceSelect做一个布型的选择框时Q由于客户需要,在特定情况下需要一个默认|也就是rich:inplaceSelect的defaultLabelQ这时就需要除了true和false外再有一个null的|所以需要将后台session bean中的对应属性由原始cdboolean改ؓBooleanQ在改完之后Q重新运行程序报错:
Property ‘xxx’ not readable on type java.lang.Boolean
分析了一下,找不Z么可能的原因Q最后在一片帖子中发现了对应的信息Q?br /> 原来JSF原始类型boolean的getҎ默认为is....(),而将装cdBoolean的getҎ默认为get...().

Ok,在后台将对应那个的方法修改,问题解决?br />

seal 2009-07-20 09:24 发表评论
]]>
Seam错误Qorg.jboss.seam.InstantiationException: Could not instantiate Seam componenthttp://www.aygfsteel.com/sealyu/archive/2009/07/17/287082.htmlsealsealFri, 17 Jul 2009 01:53:00 GMThttp://www.aygfsteel.com/sealyu/archive/2009/07/17/287082.htmlhttp://www.aygfsteel.com/sealyu/comments/287082.htmlhttp://www.aygfsteel.com/sealyu/archive/2009/07/17/287082.html#Feedback0http://www.aygfsteel.com/sealyu/comments/commentRss/287082.htmlhttp://www.aygfsteel.com/sealyu/services/trackbacks/287082.html org.jboss.seam.InstantiationException: Could not instantiate Seam component: xxxAction
找了好久Q终于发C错误原因Q?br /> 原来是对应的@Stateful的session bean对应的接口没有标注:@Local
The devil's in the DetailsQ果然如此啊


seal 2009-07-17 09:53 发表评论
]]>
在rich:inplaceSelect 中用布型的selectItem时碰到的问题http://www.aygfsteel.com/sealyu/archive/2009/07/10/286288.htmlsealsealFri, 10 Jul 2009 09:13:00 GMThttp://www.aygfsteel.com/sealyu/archive/2009/07/10/286288.htmlhttp://www.aygfsteel.com/sealyu/comments/286288.htmlhttp://www.aygfsteel.com/sealyu/archive/2009/07/10/286288.html#Feedback0http://www.aygfsteel.com/sealyu/comments/commentRss/286288.htmlhttp://www.aygfsteel.com/sealyu/services/trackbacks/286288.html
我们都知道,?lt;h:selectOneMenu>中用布型selectItemӞitemValue?true"/"false".例如Q?br /> <h:selectOneMenu  value="#{controller.booleanPropertyX}">
    <f:selectItem itemLabel="#{messages['xxxxx']}" itemValue="true"/>
    <f:selectItem itemLabel="#{messages['xxxxx']}" itemValue="false"/>
</
h:selectOneMenu>
q样是没有问题的?br /> 但是如果你?lt;rich:inplaceSelect>来实现选择功能的时候,"true"/"false"׃起作用了Q例如:
<rich:inplaceSelect minSelectWidth="80" editClass="inlineSelectEdit"
    defaultLabel="-Select-" immediate="true"
    value="#{controller.booleanPropertyX}">
    <f:selectItem itemLabel="#{messages['xxxxx']}" itemValue="true"/>
    <f:selectItem itemLabel="#{messages['xxxxx']}" itemValue="false"/>
</rich:inplaceSelect>

q时候即使sfsb中的?font size="2">booleanPropertyX?true"/"false"Q也不会有selectItem被选中Q而且如果你选择一个selectItemQ还会报?IllegalArgumentException.说明selectItem的itemValue?/font>#{controller.booleanPropertyX}的值是不匹配的?br /> 后来我将"true"/"false"改ؓ"0"/"1", q是不v作用?br />
FinallyQ终于试Z正确的方法:使用"#{true}"/"#{false}". 正确的用方法:
<rich:inplaceSelect minSelectWidth="80" editClass="inlineSelectEdit"
    defaultLabel="-Select-" immediate="true"
    value="#{controller.booleanPropertyX}">
    <f:selectItem itemLabel="#{messages['xxxxx']}" itemValue="#{true}"/>
    <f:selectItem itemLabel="#{messages['xxxxx']}" itemValue="#{false}"/>
</rich:inplaceSelect>


也就是说Q?br /> Q?Q。如果你使用<h:selectOneMenu>Q那么你的f:selectItem的itemValue应该使用Q?true"/"false"
Q?Q。如果你使用<rich:inplaceSelect>Q那么你?/font>f:selectItem的itemValue应该使用Q?#{true}"/"#{false}"

原因暂时q没研究出来Q但是结果就是这L了?br />

seal 2009-07-10 17:13 发表评论
]]>
JBoss中的TransactionTimeOut的设|?/title><link>http://www.aygfsteel.com/sealyu/archive/2009/05/18/271239.html</link><dc:creator>seal</dc:creator><author>seal</author><pubDate>Mon, 18 May 2009 02:01:00 GMT</pubDate><guid>http://www.aygfsteel.com/sealyu/archive/2009/05/18/271239.html</guid><wfw:comment>http://www.aygfsteel.com/sealyu/comments/271239.html</wfw:comment><comments>http://www.aygfsteel.com/sealyu/archive/2009/05/18/271239.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/sealyu/comments/commentRss/271239.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/sealyu/services/trackbacks/271239.html</trackback:ping><description><![CDATA[q两天在作seam的时候不旉?#8220;org.jboss.util.NestedSQLException: Transaction is not active”的错误信息,后来到jboss的wiki上发C问题的原因和解决ҎQ?br /> <h2> How do I set the Transaction Timeout?</h2> <p>Transaction timeout (unit is always seconds) can be configured in various ways:</p> <p>This argument is the same no matter if you are using JBossTM(<=4.0.5) or JBossJTA-Arjuna(>=4.2).</p> <ul> <li type="ul"> <p>Globally: You can change this behavior globally by modifying the TransactionManagerService in /conf/jboss-service.xml (or /deploy/jta-service.xml for 4.0.3)</p> </li> </ul> <p><strong>Version <= 4.0.5</strong></p> <p>This part is the same for either JBossTM or JBossJTA and is the same for ejb2 and ejb3</p> <ul> <li type="ul"> <p>Per-method basis: Modifying the <span style="font-family: courier new,courier;"><transaction-timeout></span> element inside the <method> element of a session or entity bean. This is located in the META-INF/jboss.xml deployment descriptor of a session bean. When the transaction timeout is specified at the method level, it overrides the default timeout. Further information about this element can be found in jboss-x.x.x/docs/dtd/jboss_4_0.dtd. Example taken from the testsuite:</p> </li> </ul> <ul> <li type="ul"> <p>Using BMT: Calling javax.transaction.UserTransaction.setTransactionTimeout(int seconds). Please, be aware that this only applies to transactions started after this invocation on the same thread. Example:</p> </li> </ul> <pre><code jive-java="">@TransactionTimeout(1500)<br /> </code></pre> <br /> <br /> <img src ="http://www.aygfsteel.com/sealyu/aggbug/271239.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/sealyu/" target="_blank">seal</a> 2009-05-18 10:01 <a href="http://www.aygfsteel.com/sealyu/archive/2009/05/18/271239.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Seam Cd前url的方?/title><link>http://www.aygfsteel.com/sealyu/archive/2009/05/13/270343.html</link><dc:creator>seal</dc:creator><author>seal</author><pubDate>Wed, 13 May 2009 01:36:00 GMT</pubDate><guid>http://www.aygfsteel.com/sealyu/archive/2009/05/13/270343.html</guid><wfw:comment>http://www.aygfsteel.com/sealyu/comments/270343.html</wfw:comment><comments>http://www.aygfsteel.com/sealyu/archive/2009/05/13/270343.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/sealyu/comments/commentRss/270343.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/sealyu/services/trackbacks/270343.html</trackback:ping><description><![CDATA[<p>seam有个一个内|的componentQ叫做redirect。它h获取当前view的能力当得到登陆授权后,可以直接获得d前的地址q行讉K?/p> <p>在component.xml里添加:</p> <p><event type="org.jboss.seam.security.notLoggedIn"><br /> <action execute="#{redirect.captureCurrentView}"/><br /> </event><br /> <event type="org.jboss.seam.security.postAuthenticate"><br /> <action execute="#{redirect.returnToCapturedView}"/><br /> </event></p> <img src ="http://www.aygfsteel.com/sealyu/aggbug/270343.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/sealyu/" target="_blank">seal</a> 2009-05-13 09:36 <a href="http://www.aygfsteel.com/sealyu/archive/2009/05/13/270343.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Seam错误Qdeleted entity passed to persisthttp://www.aygfsteel.com/sealyu/archive/2009/05/08/269520.htmlsealsealFri, 08 May 2009 00:59:00 GMThttp://www.aygfsteel.com/sealyu/archive/2009/05/08/269520.htmlhttp://www.aygfsteel.com/sealyu/comments/269520.htmlhttp://www.aygfsteel.com/sealyu/archive/2009/05/08/269520.html#Feedback0http://www.aygfsteel.com/sealyu/comments/commentRss/269520.htmlhttp://www.aygfsteel.com/sealyu/services/trackbacks/269520.html 单纯看错误信息,q以为是对象没有传进厅R但调试之后发现personHome里面的对象是正确的?br /> 后来试了几ơ发现是因ؓ所要删除的对象隶属于另外一个对象,那么单纯删除此对象时Q会报这个错误,因ؓ此时的约束关p还未解除?br /> 例如Q?br /> 我要删除一个Person实体Q而这个实体是属于一个组lDepartment的,
那么我应该在删除之前先执行: personHome.getInstance().getDepartment.getAllPersons().remove(personHome.getInstance()),
然后再执行personHome.remove().


seal 2009-05-08 08:59 发表评论
]]>
提高JSFQSEAME序的效率(转)http://www.aygfsteel.com/sealyu/archive/2009/05/07/269329.htmlsealsealThu, 07 May 2009 01:16:00 GMThttp://www.aygfsteel.com/sealyu/archive/2009/05/07/269329.htmlhttp://www.aygfsteel.com/sealyu/comments/269329.htmlhttp://www.aygfsteel.com/sealyu/archive/2009/05/07/269329.html#Feedback0http://www.aygfsteel.com/sealyu/comments/commentRss/269329.htmlhttp://www.aygfsteel.com/sealyu/services/trackbacks/269329.html
Speed up your Data-Driven JSF/Seam Application by Two Orders of Magnitude - Part 1
by Dan Allen
05 Feb 2009 03:00 EST

In the first of this two-part article, Dan Allen discusses some common performance problems you may encounter when using JSF components, Seam components, and the EL. You'll learn about the set of best practices for eliminating them that led to an improvement of two orders of magnitude in the performance of his application.


JavaServer Faces (JSF) has a reputation for having poor performance. Some claim that this "runtime tax" is simply the cost of using a component-based abstraction layer. After focused research, I have determined that by following a handful of best practices, you can get your JSF data tables to perform almost as well as hand-crafted HTML while still being able to retain the benefits of developing with an event-driven programming model. I begin by identifying some performance problems that occur when using JSF UI components, Seam components, and the EL carelessly, and then present, through a series of four lessons, ways to eliminate these problems one-by-one until you have observed a remarkable, two orders of magnitude improvement.

All the test results reported in this article were gathered on a Lenovo R60 with 2.5GB RAM, Dual Core T2300 @ 1.66Ghz processor running Ubuntu Linux 7.10. The application was built using Seam 2.0.3.CR1, Sun JSF 1.2_04-b16-p02, and RichFaces 3.2.2.GA. It was deployed to JBoss 4.2.2.GA running on Sun JVM 1.6.0_03. The timing results are shown in six progressive phases. Each result shows the total request time and the time to render a data table with 50 records. All metrics were captured using the FireBug extension for Firefox.

Introduction

Developing a data management application is just a matter of getting data up on the screen in tabular format, correct? Oh, right, and being able to filter the data. Ah, and also allowing the data to be changed. Unfortunately, once those challenges are behind us, we tend to wash our hands of the application and move on. But the principle goal of most web applications is to enable users to perform their work more efficiently than they did before we introduced our "solution." In fact, none of those fancy features you add have any value at all if you can't improve the user's productivity. That's why, before you step away, you have to make sure that you have addressed the issue of performance.

My colleagues and I recently completed the first stage of an open source data management application based on JSF, Seam, and RichFaces in which we addressed this very concern. The application, named EDAS2, was developed for a group of scientists for managing water quality data (stored in the WQX database schema). Now, you have to understand that these scientists, they like their data. Hordes of data. And they like to view it all at once. So much, in fact, that it tends to cause the browser to crash. Naturally, we needed to condition the scientists to some degree that browsers have limits. But regardless, we were going to be dealing with large data sets. Our goal was to make sure that working with those data sets was not painful.

This article documents the bottlenecks that we discovered and a set of best practices for eliminating them. But we went beyond merely removing obstacles in performance. We tuned the application to the point where paginating, sorting, and filtering the data is actually faster than any desktop application our scientists had ever used. Find that hard to believe? Read on.

About the EDAS2 application

The intent of the EDAS2 application is to house and analyze water-quality measurement results. The results are taken from a location, known as a monitoring location, during a given visit, known as an activity. There are various types of results, depending on what is being measured. In this article, we will be focusing on the benthic measurement result, which in layman's terms is a sampling of mud with bugs in it. That data is recorded on site and later entered into the database and analyzed using the EDAS2 interface.

There isn't anything revolutionary about the interface of the EDAS2 application. Rather, the emphasis is on efficiency. We want to provide the experience of the MS Access database-which our scientists are currently using to manage this data-in a web application.

The application has two types of views. The first is a list view, which displays a paginated table of records for the currently selected parent entity, such as monitoring location, activity, or result. You will learn shortly that what makes this interface efficient is that it offers in-place editing of each row (it also has a floating popup dialog for detailed editing of the row).

The editable data table

The key feature of this application is that the data rendered in each table can be modified in place. To implement this functionality, we decided against using an off-the-shelf grid editor from a JSF component library. Instead, we took the RichFaces step-wise approach by building a composite, Ajax-enabled component using the partial page rendering technology that the Ajax4jsf core provides.

Ajax4jsf provides a set of tag libraries that can tie a JSF generated event to the rerendering of one or more regions of the user-interface. Those regions are identified by their JSF client IDs. When the JSF event is sent to the server, instead of the JSF servlet returning an entire page response, it returns only fragments of the HTML. Ajax4jsf then cuts out the old branches from the live view and stitches in the replacements returned from the server. The result is that the user observes the page updating without any noticeable refresh, in real-time, so to speak. And Ajax4jsf's declarative approach let's us fine-tune this behavior.

Figure 1 provides a view of the editable data table with one of the rows in edit mode.

  Figure 1. The data table demonstrating its single-line editing capabilities.
Figure 1. The data table demonstrating its single-line editing capabilities.

When the page is first rendered, all rows have an edit and delete button. Clicking on an edit button puts the corresponding row in edit mode, at which point the outputs in the selected row become inputs. From edit mode, the user can make changes to the visible data and either save or cancel the update, which returns the table to read-only mode.

The strategy we use to deliver this row-level editing functionality is to have two UI components in each column of a standard JSF data table: one output component (e.g., <h:outputText>) and one input component (e.g., <h:inputText>). We then use the JSF rendered attribute on each component to control which one is displayed.

A backend supported by Seam

To support our editable data table, we put together a small hierarchy of classes that are instantiated as Seam components to manage the query (filtering, pagination) and the editing process (select row for editing, update, delete, cancel). We chose to put the components in Seam's conversation scope. The conversation scope is a slice of the HTTP session that is managed by Seam and associated with a sequence of pages through the use of a special request token (known as the conversation id). The conversation provides the developer the convenience of using the HTTP session without the memory leakage concerns, since the conversation has a much shorter lifetime and is kept isolated from other parallel conversations in the same session.

We chose to leverage the conversation for three reasons:

  • to reduce the number of times the database needs to be queried
  • to ensure the record remains managed by the persistence context while being edited
  • to maintain the search criteria and pagination offset

Using the conversation has the added bonus of making previously viewed result pages load faster since the records are already sitting in the persistence context (i.e., the first-level cache).

Given all the benefits the conversations provide, you may be wondering where the performance problem is. Let's take at look at where things began to go wrong and what we did about it.

The performance roadblock

Development was going smoothly until my colleague noticed something peculiar about the performance. Five or ten records on the page took a reasonable amount of time to render, but when that number went up to 50 or 100 records, the performance of the page plummeted. It turns out that the degradation was linear, but the slope was very steep. The page with 100 records was taking over 15 seconds to render. Obviously, that just wasn't going to fly. And so our optimization work began. Could we find the bottleneck and how low could we go?

As we optimized, we first looked at the most basic page and established a performance baseline. Then we added additional components to the page and tried to identify which ones were contributing to the major slowdown. As it turns out, in a Seam application, the first area to place your focus is on page actions, which are methods that execute before the page begins to render.

Page actions and component initialization

When a page is taking 15 seconds to render, there is likely a single culprit that is chewing up a bulk of that time. To establish a baseline, and to make sure I was focusing on the right problem, I first stripped everything from the page and requested it. The response took a couple of seconds to come back. This had me puzzled for a moment. I soon realized that that a Seam page action was registered with the page (i.e., view ID). A page action is a method-binding expression that is assigned to a JSF view ID (or a group of view IDs if a wildcard is used) in a Seam page descriptor and is evaluated by Seam just before the view ID is rendered by the JSF view handler. Here's the expression that was registered with the view ID of the results page.

<action execute="#{benthicMsmntEditor.prepareResults}" />

The page action is there to eagerly fetch the results that are to be displayed on the page. However, the query in that method was executing in about a tenth of a second. So that wasn't the problem. After studying the code a bit longer, I recognized that the problem was not in the page action method, but rather the @Create method of the component being invoked. The @Create method is a synonym to the standard @PostConstruct method in Java EE and marks a method to be evaluated immediately after a component is instantiated.

Inside the @Create method was a handful of queries that retrieved more than 10,000 records of reference data. This data is used by select menus in various forms on the page, but those forms are all being conditionally rendered. So basically, we were charging the user a toll to enter the page with a chance that that reference data would never be referenced. That brings us to lesson #1.

Lesson #1: Don't make the user pay an upfront fee to view a page. Defer logic where possible.

Since the forms are rendered conditionally, and some via Ajax, the reference data can be retrieved at the same time the forms are activated. If you must display a form unconditionally, think about the most efficient way to prepare the data (perhaps using a cache). It's also preferable to use Ajax-based autocomplete rather than select menus with a large list of options, since making this switch can drastically reduce the speed of the initial rendering of the form. The user will likely be more patient when working on the field with autocomplete, and you can even keep the number of options delivered to a minimum as the user types.

With the toll skimmed off the top, we could get back to the performance of the elements on the page. Bringing back the page piece-by-piece, I determined that the next big time hog was in fact the data table. Again, I stripped out elements in the data table until I pinned down what was causing the problem. As it turns out, it was the expressions in the rendered attributes that I was using to hide or show various components in the table.

The cost of conditional rendering

In each row there are 6 "editable" columns, each containing an output and an input component and 4 icons for controlling editing (edit, delete, approve, cancel). In total, there are 16 uses of the rendered attribute appearing in each row. (Initially I had a couple columns with multiple input components, which I realized I needed to group within a panel group [i.e., <h:panelGroup>] so that the rendered attribute was only applied once).

As you know, logic that occurs in a single row is multiplied by the number of rows in the table. In a table with 100 rows, there are 1600 uses of the rendered attribute! But wait, there's even more! The rendered attribute is a nasty beast in JSF because it's often evaluated multiple times as the UI component tree is assembled. In fact, during the render response phase, it's resolved 3 or 4 times per component in a data table. What that means is that for our data table, the conditional rendering logic we are using is executed 5200 times for 100 rows! Whatever that logic is better be darn efficient or else it will have a huge impact on performance.

Warning: After hearing the bad news about how the rendered expression is abused by JSF, you might be inclined to use the <c:if> tag from Facelets. This tag emulates the behavior of the equivalently named tag from the JSTL tag library. You have to be careful with this tag, though, because it's not a true JSF component. It's processed by the Facelets compiler prior to building the UI component tree and can thus exclude a region of the markup from contributing to the UI component tree for that view. The benefit of this tag is that it can reduce the size of the component tree when you know that certain parts of the page aren't needed. However, the conditional rendering that you expect to happen on a postback does not, because at that point, the tree is already built and Facelets does not reprocess the <c:if> statements.

As it turns out, we were not being very efficient. Let's take a look at one of the columns of the data table in the /BenthicMeasurementList.xhtml view template:

<h:column> <f:facet name="header">Taxonomic Unit</f:facet> <h:outputText value="#{_item.taxon.name}" rendered="#{!benthicMsmntEditor.editing(_item)}"/> <h:selectOneMenu id="taxonomicUnit" rendered="#{benthicMsmntEditor.editing(_item)}" defaultLabel="No value set" value="#{_item.taxon}"> <s:selectItems value="#{taxonValues}" var="_taxon" label="#{_taxon.name}" noSelectionLabel="No value set"/> <s:convertEntity/> </h:selectOneMenu> </h:column>

As you can see here, I am calling the editing() method on a Seam component named benthicMsmntEditor to test whether the current row is in edit mode. We can pass the iteration variable, _item, to the method because Seam integrates with the JBoss EL, which introduces parameterized method calls to the Unified EL. The editing() method performs an identity check between the row data and the selected row.

public boolean editing(T itemInRow) { return itemInEditMode == itemInRow; }

Here we are only allowing one row to be in edit mode at a time, but this logic could easily be enhanced to support editing multiple rows simultaneously.

So where's the bottleneck? Initially, you may be inclined to point the finger at the EL or Java reflection. I did some testing and determined that the EL is surprisingly fast and Java reflection is equally optimized. And if you are inclined to believe that the slowness is caused by the parameterized method call, I'll inform you that comparing the current item using an EL operator to the item in edit mode retrieved using the JavaBean style accessor yields the same timing results:

rendered="#{_item == benthicMsmntEditor.itemInEditMode}"

The culprit is that the editing() method resides on a Seam component and each method call to a Seam component passes through a stack of interceptors, unless otherwise skipped by the presence of the @BypassInterceptors annotation at the component or method level.

When you call an intercepted method once, you would never notice the impact of the interceptors. However, when you call the method 5200 times, the time spent in the interceptors adds up. How much of a difference does it make and what other options do we have?

To determine the impact, I timed both the rendering of the entire page and the rendering of the data table region, as described in the introduction. The data table region consists of the data table and the pagination controls and summary information for the table. A test of 4 requests on 50 rows (2600 calls) produced these timing results:

Stage 1 timing results (50 rows)
Request Elapsed time of request (ms) Time to render table (ms)
1 6330 6090
2 6340 6096
3 6400 5883
4 6100 5850
avg 6292.4 5979.8

Not many people are going to stick around for a page that takes 6 seconds to render (in the best case scenario), and that doubles for 100 rows. The trick is to outject the selected row so that the comparison can be done without having to invoke a Seam component. Outjection is a mechanism in Seam that takes the value of a JavaBean property on a component and assigns it directly to the name of a variable in the specified scope (such as the conversion scope). You outject a property by annotating it with the @Out annotation, as shown here:

@Out(required = false) private T itemInEditMode;

(For readers with Seam experience, there is a reason why you cannot simply add @BypassInterceptors to the editing() method, which I will provide in a moment.)

Now we can check if the row is in edit mode by comparing the iteration variable in the data table to the outjected property using the following EL expression in the view:

"#{item == itemInEditMode}"

Here's how things improve after making this change:

Stage 2 timing results (50 rows)
Request Elapsed time of request (ms) Time to render table (ms)
1 904 663
2 807 608
3 813 569
4 823 592
avg 836.8 608

Less than one second is certainly a nice place to be. We can do better, but let's first focus on the 5 second discrepancy because it is a cause of concern regarding Seam's performance.

The truth is, interceptors come with a cost. Again, this cost only adds up when you are pounding the component, like the rendered attribute does. Unfortunately, that is more of a limitation (and a fact of life) in the way that the data table component in JSF was designed. On the other hand, that is why Seam provides the @BypassInterceptors annotation. This annotation is intended to be used on methods that read the state of a component, as opposed to a method with behavior. After all, Seam is a stateful framework and espouses using objects as they were intended, to have behavior and state.

So why not just add @BypassInterceptors to the editing() method to reduce the overhead of invoking it? Theoretically that would work. The only problem is that Seam relies on interceptors to restore the state of conversation-scoped components, at least in Seam 2.0. In Seam 2.1, this behavior is disabled by default, so you could just add @BypassInterceptors to the method. However, if you plan to use stateful session beans (SFSBs) in your application or run the application in a cluster, you will need to enable the behavior I am about to describe, so it's important to understand why interceptors on conversation-scoped components are important.

Seam's managed entity interceptor

Seam 2.0 uses an interceptor that aids with maintaining the object identity of persistent objects (managed entities) across passivation of a SFSB, or when components jump nodes in a cluster. This interceptor has good intentions, but can have bad consequences. At the end of a method call on a conversation-scoped component, the interceptor transfers the values of all fields holding references to entity instances directly into the conversation context, and then nullifies the values of those fields. It reverses the process at the beginning of the next call. The consequence is that without interceptors, your conversation-scoped object is missing state. Eeek! What's worse is that the performance of the interceptor is naturally challenged if your component happens to be storing large data sets, because it takes time for the interceptor to perform its work. It's an unfortunate sacrifice in order to achieve transparent replication.

Rather than worrying about whether to use this interceptor, or locking the design of your application into its absence, it's best just to avoid the need to disable interceptors. Besides, there are still other interceptors that may need to be enabled on a component's methods (its all or nothing when you disable them) and working with outjected data is the fastest approach anyway. You can feel comfortable calling methods on Seam components in other areas of your page, but you should avoid doing so inside of a data table, which brings us to our second lesson.

Lesson #2: Don't call intercepted methods inside a data table (or in excess)

The question is, have we done all that we can do to optimize? Not even close. There is another important lesson to learn, and this one has to do with the EL, or more specifically, the EL resolver mechanism.

Resolving variables efficiently

In JSF, the view is bound to server-side components using a syntax known as the Unified Expression Language (EL). The root of an EL string (e.g., #{itemInEditMode}) is presumed to be a variable in one of the available web application scopes, or the name of a component that must be created (such as a JSF managed bean or Seam component). The name resolution is handled by the EL resolver chain, which is a collection of objects that know how to locate or create objects that map to a name. All resolvers in the chain are consulted until the end of the chain is reached or a value is found. This lookup happens a tremendous number of times while rendering a JSF view, especially while rendering a data table. Thus, it's a potential source of performance problems.

As the EL resolver chain seeks out a variable, it becomes increasingly more aggressive. The standard EL resolver looks in the familiar places: the request, session, and application scope. It then turns the task over to the Seam resolver, which is where things start to slow down. Seam has lots of different places to look to resolve a variable: a component, a factory, a Seam namespace, a Seam context, and the list goes on. Thus, not finding a variable comes at a high cost.

So the solution is simply to avoid referencing a missing variable, right? Well, what happens when a null value for a variable is meaningful in your application, as is the case of our editable data grid. A null value for the itemInEditMode variable means the row is not in edit mode. Unfortunately, the EL resolver chain doesn't know that a null value means something, and will keep working through its crib sheet until it has tried all possible combinations. Thus, we need to find some way to tell Seam exactly where to look rather than allowing Seam to send out its search party, so to speak.

Again, taking advantage of the flexibility afforded to us by the JBoss EL, we can reach directly into the conversation context to look for the row in edit mode:

rendered="#{_item == conversationContext.get('itemInEditMode')}"

Here's the reward we get for telling Seam exactly where to look:

Stage 3 timing results (50 rows)
Request Elapsed time of request (ms) Time to render table (ms)
1 491 207
2 495 224
3 493 201
4 444 211
avg 480.8 210.8

We roughly doubled our performance and now have 100 rows coming in under a second, with an order of magnitude improvement over the first run. But there is still a slight bottleneck. The variable _item is stored in request scope by the data table and is resolved quickly, but the variable conversationContext is a pseudo-variable that Seam interprets after looking in all the usual places for a real variable named conversationContext. Not only that, conversationContext is an imported context variable, the qualified name being org.jboss.seam.context.conversationContext. It turns out that referencing a context variable in an imported namespace has a measurable cost associated with it. A better choice would be to pull the result of this lookup somewhere closer so that Seam doesn't have to keep searching for it. We can set that up using an alias (an event-scoped factory) in the Seam component descriptor named conversationScope (to match requestScope, sessionScope, and applicationScope provided by the standard EL resolver):

<factory name="conversationScope" value="#{conversationContext}"/>

We now reference this name in our rendered logic:

rendered="#{_item == conversationScope.get('itemInEditMode')}"

Here's how the timing results improve:

Stage 4 timing results (50 rows)
Request Elapsed time of request (ms) Time to render table (ms)
1 399 161
2 373 150
3 458 207
4 560 163
avg 447.5 170.25

Those are the kinds of numbers we want to see! Just as I mentioned at the start of this article, there was likely a single culprit that was squandering a majority of the rendering time. It turns out to have been the logic in the rendered attribute of components within a data table. But really any logic inside of a data table has to be optimized because it's going to be compounded by the number of rows being rendered. For instance, you might be conditionally rendering columns based on the user's preferences. That brings us to the third lesson.

Lesson #3: Be extremely frugal with the logic you use within a data table

Incidentally, I thought about using an action listener to toggle the rendered state on components in a row when the user clicks on the edit button, since that's the "object-oriented" way of doing things. Unfortunately, the design of the data table is extremely naive and does not support this usage pattern. A data table doesn't have any concept of rows, only columns. The rows are introduced dynamically based on the data fed to the table (they are not represented in the state of the component tree). Thus, if you change the rendered attribute on a component in one of the rows, you end up affecting every row in the table. The dynamic nature of the data table leads to many other problems in JSF, including the "ghost click" which I discuss in my book, Seam in Action

If you are committed to squeezing as much performance as possible out of your page, then there is one more way you can optimize the speed of the rendered logic: don't use it. I'm not suggesting that we throw out the editable grid functionality. If you think about it, that logic only needs to be performed once the user has selected a row. Before that time, you know that you only need to display the table in read-only mode (and you know which controls to provide in that case). Thus, the best thing to do is split the table into two, one that has the rendered logic in the columns and one that does not, then toggle the rendering of the entire table. That way, the person just browsing the data does not have to pay the tax of checking for the row selected for editing. While this does increase the amount of code to maintain, it introduces the possibility of having different columns displayed when the user is editing than when they are just viewing (or even having the table look different in some way). You can move common code into templates to prevent duplication. Of course, the performance is now going to increase noticeably.

Stage 5 timing results (50 rows)
Request Elapsed time of request (ms) Time to render table (ms)
1 537 174
2 355 127
3 372 127
4 374 127
avg 409.5 138.8

You are probably feeling pretty happy with the progress so far. Where to next? In each of the performance results, I have provided two columns of data for a reason: to emphasize that we are paying yet another tax to render the remainder of the page. That is the focus of the next round of optimizations. Obviously, the size of this tax is going to depend on what else you have on your screen and won't necessarily amount to the ~270ms appearing in these test results. Regardless, the amount of this tax now exceeds the cost of the product and we need to do something about it. That's where Ajax comes in.

Cutting costs with Ajax

The bottleneck in any decently performing web application is the process of the browser requesting and ultimately rendering a new page. What makes the process worse is that it happens synchronously, forcing the user to wait until it finishes. It's extremely disruptive and it makes the application feel slow. A far better approach is to have the browser only replace the portions of the page that need to be changed and to insert those changes into the page when they arrive (i.e., partial page rendering), which doesn't interrupt what the user is currently doing (or at least keeps the disruption localized).

The exchange just described is achieved using Ajax. Fortunately, the RichFaces component library for JSF makes adding Ajax interactions to a page extremely straightforward. In the next part of this article, you'll learn to use RichFaces' partial-page rendering to only update the data table when the user change its state, such as to select a row for editing or paginating the table, thus eliminating the tax that comes with rerendering the entire page. Once this change is made, the two orders of magnitude performance boost will be realized.


Speed up your Data-Driven JSF/Seam Application by Two Orders of Magnitude – Part 2
by Dan Allen
27 Mar 2009 01:30 EDT

In the second installment of this two-part article, Dan Allen continues his discussion of some common performance problems you may encounter when using JSF components, Seam components, and the EL. You'll learn about the set of best practices for eliminating them that led to an improvement of two orders of magnitude in the performance of his application.


In the first part of this article, I began briefing you on optimizations I made to maximize the responsiveness of a JSF application that I developed out in the field. I cited performance problems caused by casually accessing components from a JSF view, then presented a set of best practices to eliminate this unnecessary overhead. Despite the progress made by the end of the first part, you had not yet witnessed the two orders of magnitude in performance improvement that was promised.

In this part, the additional gains will be achieved by leveraging partial page rendering-provided by the RichFaces JSF component library and by slimming the response. Partial page rendering cuts out the overhead of rerendering the entire page after each user interaction, which turns out to be the real bottleneck in most traditional web applications, and instead redraws only the areas of the page that have changed. Naturally, you want the replacement HTML source to be as condensed as possible. These optimizations allow the responsiveness of a web application to measure up to its desktop counterpart.

Tapping into Ajax

When the user performs an operation on the screen, such as selecting a row for editing or paginating a result set, we only want to rerender the area of the page that is affected. Using the data-driven application presented in the first part, that means redrawing the data table and its pagination controls. (Note that it's possible with Ajax4jsf to rerender a single row, when applicable, but I have found it to be more trouble than it's worth).

Putting numbers aside, using Ajax is going to make the application feel far more responsive because the browser does not have to bootstrap a whole new page and all the assets that come along with it. Research has shown that creating HTTP connections is more costly than rendering large pages. Partial page rendering accounts for these findings by treating the static areas of the page and its associated assets as completed work, and focusing solely on retrieving updates. This section will support my recommendation that you should always consider using Ajax in your application, as it truly does eliminate a lot of overhead.

Accessible Ajax with Ajax4jsf

Turning regular JSF postbacks into Ajax requests is pretty simple with Ajax4jsf. However, if used inappropriately, you won't get all the performance gains you are looking for. We'll get to that in a second. First, begin by changing your <h:commandLink> and <h:commandButton> components to the ones from Ajax4jsf: <a:commandLink> and <a:commandButton>. Next, select what you want to rerender. You reference the areas of the page to update using a comma-separated list of the regions' component IDs in the reRender attribute of the command component. If you are paginating, you need to rerender the whole table and the pagination controls (dataTableContainer). If you are transitioning into edit mode, there's no need to requery or update the pagination, so you only have to rerender the table itself. Here's the code for the pagination controls:

<a:commandLink id="previous" action="#{benthicMsmntEditor.previous}" rendered="#{benthicMsmntEditor.previousAvailable}" reRender="dataTableContainer" ajaxSingle="true"> <h:graphicImage value="/img/previous.png" alt="Previous" title="Previous"/> </a:commandLink> <a:commandLink id="next" action="#{benthicMsmntEditor.next}" rendered="#{benthicMsmntEditor.nextAvailable}" reRender="dataTableContainer" ajaxSingle="true"> <h:graphicImage value="/img/next.png" alt="Next" title="Next"/> </a:commandLink>

The code for the edit control buttons in each row is similar. Here's how the edit button is defined: <a:commandLink id="edit" action="#{benthicMsmntEditor.editItem}" rendered="#{_item != conversationScope.get('itemInEditMode')}" reRender="dataTable" ajaxSingle="true"> <h:graphicImage value="/img/edit.png" alt="Edit" title="Edit"/> </a:commandLink>

What's important about using an Ajax request is to keep it simple. You don't want to perform a lot of processing on the server because then the users aren't going to get the "instant" feedback they are expecting. You can drastically reduce the portion of the component tree that is processed by JSF by using either the <;a:region> tag or the ajaxSingle attribute on an Ajax4jsf component. Let's focus on ajaxSingle.

Keeping the Ajax call brief

By default, JSF processes the whole component tree on a postback because it doesn't know where events may originate or which input fields within the submitted form contain new data. What the ajaxSingle attribute does is tell JSF to advance directly to the component that was activated, process events from that component, and re-encode it as if it were the only component on the page. The result is a drastic speed increase in the processing, independent of the size of the component tree. In fact, the only time you would forgo using ajaxSingle is when you need to capture input data from a form (a classic form submit).

When deciding whether or not to use this attribute, ask yourself if you are capturing form data or whether JSF is simply using the form submit to perform server-side work (a contrived form submit). In JSF, it's most often the latter.

Note: Interestingly enough, ajaxSingle is also a drop-in replacement for immediate, which is excellent since immediate is so poorly understood. When ajaxSingle is placed on a command component (such as a button), the form data is not processed, and hence no validation/conversion failures can occur, thus eliminating the need for immediate.

Having shifted all interactions to the Ajax bridge, it's now time to look at the performance gains. Of course, when using Ajax, the tax of rendering the portions of the page outside of the data table is gone. The performance on the server is also no longer a primary concern. Now what matters is the size of the response. Unfortunately, giving timing results here would be arbitrary because it's highly dependent on the speed of the network (and I'm testing against my own box). We have to focus on what we can control.

Trimming down the response

So what affects response size? The answer is, every character in the view. Every character that you type that is encoded into the response, as well as the markup that the JSF components generate, affects the size of the response. That includes:

  • Component IDs
  • View IDs
  • The path of images, external JavaScript files, and CSS
  • The application context path
  • Embedded JavaScript
  • Inline styles and names of style classes
  • Erroneous markup that is encoded into the response

As you can see, there's lots of room for improvement in this category. I want to focus on component IDs first, since they are the biggest culprit.

Resources


Dan Allen is a Senior Software Engineer at Red Hat and author of Seam in Action. He has over eight years of development experience using technologies that include Java frameworks (Seam, JSF, EJB3, Hibernate, Spring, Struts), testing frameworks (JUnit, TestNG), JavaScript and DOM scripting, CSS and page layouts, Maven 2, Ant, Groovy, and many others.

After graduating from Cornell University with a degree in Materials Science and Engineering in 2000, Dan became captivated by the world of free and open source software, which gave him his debut in software development. He soon discovered the combination of Linux and the Java EE platform to be the ideal blend on which to build his professional career, with his interests equally divided between the two platforms.

Dan is a member of the Seam project, a dedicated open source advocate, and a Java blogger. He lives with his extremely supportive wife in Laurel, MD. You can keep up with Dan's development experiences by subscribing to his blog at Mojavelinux





seal 2009-05-07 09:16 发表评论
]]>
谈Seam 中的取数据的问题和@Factory的?/title><link>http://www.aygfsteel.com/sealyu/archive/2009/05/06/269248.html</link><dc:creator>seal</dc:creator><author>seal</author><pubDate>Wed, 06 May 2009 07:30:00 GMT</pubDate><guid>http://www.aygfsteel.com/sealyu/archive/2009/05/06/269248.html</guid><wfw:comment>http://www.aygfsteel.com/sealyu/comments/269248.html</wfw:comment><comments>http://www.aygfsteel.com/sealyu/archive/2009/05/06/269248.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/sealyu/comments/commentRss/269248.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/sealyu/services/trackbacks/269248.html</trackback:ping><description><![CDATA[<br /> 作者: sealyu   日期Q?009-05-06<br /> <br /> 在Seam中,如果要提供一个集合属性传到页面,那么可以有两U选择Q?br /> Q?).在SFSB中徏一个集合属性,q徏立一个方法用来取得对应的数据。例如我们有一个SFSBQTestAction.javaQ:<br /> QStateful  <br /> @Name("testPerson")<br /> public class TestAction extends TestActionLocal implements Serializable{<br />   protected List<Person> personList;<br />   public List<Person> getPersonList(){<br />       //得到对应数据<br />   }<br /> }<br /> 每次在前台页面调用的时候可以直接用:<br /> <rich:dataTable value="#{testPerson.personList}" id="xxx"/>.<br /> <br /> 但是q种Ҏ有种~点Q因为将对应的D值给一个JSFlgQ所以在h一个页面的时候经帔R要调用很多次取数据的函数Q即使你作判断(例如Q当g为空的时候不再重新取|Q这个函数还是会执行很多ơ,可能会造成效率的问题?br /> 但是q种Ҏ的好处是L可以取得最新的数据。在你经帔R过传递参数来取得数据列表的时候,q种Ҏ比较好?br /> Q?).使用QFactory. <br /> QFactory有两U,在它的javadoc里面是这么说的:<br />  * Marks a method as a factory method for a context variable.<br />  * A factory method is called whenever no value is bound to<br />  * the named context variable, and is expected to initialize<br />  * the value of the context variable. There are two kinds of <br />  * factory methods. Factory methods with void return type are <br />  * responsible for outjecting a value to the context variable. <br />  * Factory methods which return a value do not need to <br />  * explicitly ouject the value, since Seam will bind the<br />  * returned value to the specified scope.<br /> <br /> <strong>W一U工厂方?</strong><br /> q种工厂Ҏ没有q回|但是你需要将得到的数据注出到context里面Q大多数情况下你可以直接使用QDataModelQ例如:<br /> QStateful  <br /> @Name("testPerson")<br /> public class TestAction extends TestActionLocal implements Serializable{<br />   @DataModel<br />   protected List<Person> personList;<br />   @Factory(value="personList", autoCreate=true)<br />   public void getPersonList(){<br />       //得到对应数据<br />      this.personList=mgr.createQuery....<br />   }<br /> }<br /> <br /> <strong>W二U工厂方法:</strong><br /> q种工厂Ҏ有返回|seam会根据scope的值将数据l定到对应的上下文中。用这U方法,你不用显式的注出。例如:<br /> <br /> QStateful  <br /> @Name("testPerson")<br /> public class TestAction extends TestActionLocal implements Serializable{<br />   protected List<Person> personList;<br />   @Factory(value="personList", autoCreate=true)<br />   public List<Person> getPersonList(){<br />       //得到对应数据<br />      this.personList=mgr.createQuery....<br />      return personList;<br />   }<br /> }<br /> <br /> 不管使用哪种ҎQ你都可以在面中直接访问这个factory的|<br /> <rich:dataTable value="#{personList}" id="xxx"/><br /> <br /> 使用QFactory的好处是不用重复的去取|但是同时也有一个缺点:<br />   使用@Factory的时候,只有在context中没有这个@Factory所对应的绑定值的时候,seam才会重新执行工厂Ҏ来取得这个倹{所以如果你惌在CRUD一个实体之后更新列表的话,你可以监听org.jboss.seam.afterTransactionSuccess.XXEntity事g来更新这个@Factory的倹{暂时没扑ֈ强制清空q刷斎ͼFactory的方法,seam好像现在q没有提供这个方法,所以我现在是直接清I@Factory所对应的list的值来辑ֈh的目的?br /> <br /> <br /> <img src ="http://www.aygfsteel.com/sealyu/aggbug/269248.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/sealyu/" target="_blank">seal</a> 2009-05-06 15:30 <a href="http://www.aygfsteel.com/sealyu/archive/2009/05/06/269248.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在xhtml中用空?/title><link>http://www.aygfsteel.com/sealyu/archive/2009/04/29/268052.html</link><dc:creator>seal</dc:creator><author>seal</author><pubDate>Wed, 29 Apr 2009 02:21:00 GMT</pubDate><guid>http://www.aygfsteel.com/sealyu/archive/2009/04/29/268052.html</guid><wfw:comment>http://www.aygfsteel.com/sealyu/comments/268052.html</wfw:comment><comments>http://www.aygfsteel.com/sealyu/archive/2009/04/29/268052.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.aygfsteel.com/sealyu/comments/commentRss/268052.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/sealyu/services/trackbacks/268052.html</trackback:ping><description><![CDATA[在xhtml面中加入空g能?&nbsp;" 要?nbsp; <div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img src="http://www.aygfsteel.com/images/OutliningIndicators/None.gif" align="top" alt="" /><span style="color: #000000">&</span><span style="color: #000000">#</span><span style="color: #000000">160</span><span style="color: #000000">;</span></div><img src ="http://www.aygfsteel.com/sealyu/aggbug/268052.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/sealyu/" target="_blank">seal</a> 2009-04-29 10:21 <a href="http://www.aygfsteel.com/sealyu/archive/2009/04/29/268052.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>h:panelGrid 属性详??http://www.aygfsteel.com/sealyu/archive/2009/04/24/267269.htmlsealsealFri, 24 Apr 2009 00:34:00 GMThttp://www.aygfsteel.com/sealyu/archive/2009/04/24/267269.htmlhttp://www.aygfsteel.com/sealyu/comments/267269.htmlhttp://www.aygfsteel.com/sealyu/archive/2009/04/24/267269.html#Feedback0http://www.aygfsteel.com/sealyu/comments/commentRss/267269.htmlhttp://www.aygfsteel.com/sealyu/services/trackbacks/267269.html <h:panelGrid >样式表基本概?
单元格样?  columnClasses="columnClasses1, columnClass2,..."  <==>  <td class="columnClasses1">....<td class="columnClasses2">
行样?  rowClasses="rowClasses1, rowClasses2"  <==>  <tr class="rowClasses1">....<tr class="rowClasses2">
样式:  styleClass=""  ==  <table class="">
?  无法实现多个表头单元.

panelGrid 标签学习
q个标签可以用来作简单的lg排版Q它会用HTML表格标签来绘制表|q将lg|于其中Q主要指定columns属性,例如讑֮?2Q?
<h:panelGrid columns="2">
<h:outputText value="Username"/>
<h:inputText id="name" value="#{userBean.name}"/>
<h:outputText value="Password"/>
<h:inputText id="password" value="#{userBean.password}"/>
<h:commandButton value="submit" action="login"/>
<h:commandButton value="reset" type="reset"/>
</h:panelGrid>
则自动将lg分作 2 ?column来排列,排列出来的样子如下:


<h:panelGrid>的本体间只能包括JSFlgQ如果想要放入非JSFlgQ例如简单的LQtemplateQ文字,则要使用 <f:verbatim>包括住,例如Q?
<h:panelGrid columns="2">
<f:verbatim>Username</f:verbatim>
<h:inputText id="name" value="#{userBean.name}"/>
<f:verbatim>Password</f:verbatim>
<h:inputText id="password" value="#{userBean.password}"/>
<h:commandButton value="submit" action="login"/>
<h:commandButton value="reset" type="reset"/>
</h:panelGrid>



<h:panelGroup>
q个lg用来数个JSFlg包装hQ其看来像是一个组Ӟ例如Q?
<h:panelGrid columns="2">
<h:outputText value="Username"/>
<h:inputText id="name" value="#{userBean.name}"/>
<h:outputText value="Password"/>
<h:inputText id="password" value="#{userBean.password}"/>
<h:panelGroup>
<h:commandButton value="submit" action="login"/>
<h:commandButton value="reset" type="reset"/>
</h:panelGroup>
</h:panelGrid>
?lt;h:panelGroup>中包括了两个<h:commandButton>Q这使得< h:panelGrid>在处理时Q将那两?lt;h:commandButton>看作是一个组件来看待Q其完成的版面配|如下所C:


下面转蝲与http://blog.csdn.net/liyong1115/archive/2008/02/27/2125029.aspx
一、初识panelGrid和与之相关的设计元素

panelGrid相当于HTML的表|在设计中与之相关的组件有panelGropQ与之相配合的CSS

设计元素有styleClass、headerClass、footerClass、rowClasses、columnClasses。这些元

素的有机l合Q可以设计出不同的输出画面?

在HTML|页设计中,表格?lt;table><tr><td>{标记符P也可以在标记W号内嵌入CSS?

制语句来控制输出的表现Ş式。JSF中的panelGrid虽然与HTML表格相对应,但是二者在设计?

q是有很大差异的。例如我们假设有一个HTML的表如下Q?

<table>
<tr>
<td>...</td>
<td>...</td>
</tr>

<tr>
<td>...</td>
<td>...</td>
</tr>
</table>

则panelGrid与之对应的标记是Q?

<h:panelGrid column="2">
...
...
...
...

</h:panelGrid>

它只有外x讎ͼ没有行控制和列控制标记?

熟悉HTML~程的道Z眼就看出Q只有外x讎ͼ你该怎样控制行或列的输出样式呢??

急,JSF设计者已l想CQ他们设计出

了styleClass、headerClass、footerClass、rowClasses、columnClassesq些设计元素来控

制行与列的输出样式,其中
styleClass是格式表格ȝ外观的,如表格的长与宽、外Ҏ样式、表格的背景样式{?
headerClass、footerClass分别是控制表的header和footer的?
rowClasses和columnClasses分别是控制表格的行与列样式的?

q是举个例子说一下,我们有下例:

<h:panelGrid columns="1" cellpadding="5"
styleClass="styleClazz"
headerClass="headerClazz"
footerClass="footerClazz"
rowClasses="row1,row2"
columnClasses="column1"
>

<f:facet >
<h:outputText value="您好Q朋友!"/>
</f:facet>

<h:outputText value="您好Q朋友!"/>
<h:outputText value="您好Q朋友!"/>
<h:outputText value="您好Q朋友!"/>
<h:outputText value="您好Q朋友!"/>
<h:outputText value="您好Q朋友!"/>
<h:outputText value="您好Q朋友!"/>

<f:facet >
<h:outputText value="您好Q朋友!"/>
</f:facet>
</h:panelGrid>

q就是一个表|columns="1"Q规定这个表只有一列,cellpadding="5"说明了边框外U?

与内U的距离?个像素。这个表׃个头部、一个尾部和中间表n三部分组成。headerClass

是格式头部样式的QfooterClass是格式尾部样式的QrowClasses和columnClasses是格式行?

列样式的?rowClasses="row1,row2"规定了表格的行与行交替用row1和row2样式cL格式

输出样式Q同P列也是,q且q可以用3个?个或更多个row3、row4...来依序交替格式输

出样式?

对应的样式类可以像以下这L写在css文g中:


/*styleClass处于父类的地?headerClazz,rowClasses{的字体讄取em?
其在屏幕上显C的大小会参照该cd体的大小讄而放大或~小*/

.styleClazz{
font-size:1em;
color:blue;
border-style:solid;
border-color:red;
border-width: 1px;
}

.headerClazz{
background-color:#3F536B;
font-family:宋体;
font-size:1.5em;
color:white;
text-align:center;
}

.footerClazz{
background-color:#3F536B;
font-family:宋体;
font-size:1.5em;
color:white;
text-align:center;
}

/* 当行样式与列样式都用?则行样式服从于列样式
Ҏ的颜色需要在columnClasses中定?
在rowClasses中定义不起作?
*/

.row1{
background-color:#FFFFFF;
}

.row2{
background-color:#C9D3E0;
}

.column1{
border-style:solid;
border-color:red;
border-width: 1px;
}

.column2{
}


你可以用CSS在JSP中的语法其~写在JSP文g中?

二、panelGrid如何来格式成h拆分合ƈ样式的表

q要用到panelGroupQ它的作用是封装在内的元g作ؓ一个元件来看待Q如果panelGroup

中封装了一个panelGridQ则被封装的表放在其他表中就相当于一个子表。通过panelGroup来封

装各UIlg的办法,可以实现表格的拆分目的?

<h:panelGroup>
<h:panelGrid>
...
</h:panelGrid>
</h:panelGroup>

或者:

<h:panelGroup>
<h:outputText value="您好Q朋友!"/>
<h:outputText value="您好Q朋友!"/>
</h:panelGroup>

它们在容器中相当于一个显C元?好像本来是一个h住一间房Q现在是更多的h住一间房)?

三、如何在panelGrid中实现设计元素对?

panelGrid是通过CSS语言来格式输出样式的Q在CSS语言中可用vertial-align:...;来格

式输出元素纵向对齐,使用text-align:...;来实现输出元素横向对齐。其中text-align有点

qL人,因ؓ从字面看它应该是针对文本的,其实它对其他元素也v作用?

在对齐的设计中有个居中对齐的问题Ҏlh。在HTML中可?lt;center>...</center>来实

现被装的视囑օ素居中,但在CSS中好像没有类D句。其实还是有的,只不q绕了一个弯

。你惛_Q说到居中,那究竟是在多宽的范围内居中?是我q个元素在封装我的容器中居中Q?

q是被我装的元素在我这个容器中居中Q这个问题CSS与HTML处理语义是不L?

在HTML中表格居中是Q?
<table align="center">
...
</table>

表格在这里的居中是指q个表格“?#8221;在封装我的容?lt;body>中居中,具体表现为在屏幕上居

中,但是您不能通过

<h:panelGrid align="center">
...
</h:panelGrid>

来实现panelGrid?lt;body>中居中。因为panelGrid标记Ҏ不支持这个语句。还是要通过CSS

来实现。下面这个用CSS语句描述居中的语义与HTML使用align="center"语义不同?

<h:panelGrid style="text-align:center">
<h:outputText value="您好Q朋友!"/>
</h:panelGrid>

q个语句说的是meq个对象在panelGrid 中居中,而不是指表格?lt;body>(屏幕)中居中。我

要在屏幕中居中怎么办?有两U办法,一U是通过?lt;body>中加入格式说明,W二U办法是?

panelGrid的外面再套一个panelGrid。即Q?


<h:panelGrid style="text-align:center;width=979px;">

<h:panelGroup>
<h:panelGrid style="text-align:center">
<h:outputText value="您好Q朋友!您好Q朋友!"/>
<h:outputText value="您好Q朋友!"/>
<h:outputText value="您好Q朋友!"/>
</h:panelGrid>
</h:panelGroup>

</h:panelGrid>

q样实C被封装的panelGrid B ?A 中居中,注意Q这里的width=979px;是必ȝQ它

规定了居中是在多宽的范围内居中!数字多少可以调整Q但是你不能不写q个U定Q否则,?

装在里面的panelGridq是不会在屏q上居中?

q有一Ҏ意,里面panelGrid B 的text-alignl承外面panelGrid A 中的text-align?

性的U定Q即里面的panelGrid不写style="text-align:center"Q对象me们也会在?

面panelGrid中居中。但是里面的panelGrid不承外面的widthQ像上面Q里面panelGrid的显

C宽度与最长的me1有关Q而不是外面panelGrid A的宽?79px?

四、其?
■当屏幕的显式格式是1024 X 768 Ӟ最外面的panelGrid宽度?79px是屏q最大化?

底部滚动条由出现C出现的界|如超q?79则滚动条׃出现?
■可以按照是?lt;table><tr>q是?lt;td>起作用的CSSc,q行装。如写在style语句?

Q则形如下:

<h:panelGrid style="width:240px;vertial-align:top;text-align:center;">
...
</h:panelGrid>


<h:panelGrid id="Grid" border="1" columns="2" rowClasses="rowClasses" cellspacing="cellspacing" cellpadding="cellpadding" columnClasses="columnClasses">
      <h:outputText value="item1"></h:outputText>
       <h:panelGroup layout="block" >
         <h:outputText value="item4-panelGroup"></h:outputText>
       </h:panelGroup>
</h:panelGrid>

           <h:outputLink  styleClass="newlink" > 
         <h:outputText   escape="false" value=" <STRONG> 默认论坛版面 </STRONG> " />  
            </h:outputLink>

<a href="" class="newlink"> <STRONG> 默认论坛版面 </STRONG> </a>

<table id="j_id_jsp_1725709284_1:Grid" border="1" cellpadding="cellpadding" cellspacing="cellspacing">
<tbody>
<tr class="rowClasses">
<td class="columnClasses">item1</td>
</tr>
<tr class="rowClasses">
<td class="columnClasses">item4-panelGroup</td>
</tr>
</tbody>
</table>

seal 2009-04-24 08:34 发表评论
]]>
Seam安全{略Q{Q?/title><link>http://www.aygfsteel.com/sealyu/archive/2009/04/23/267164.html</link><dc:creator>seal</dc:creator><author>seal</author><pubDate>Thu, 23 Apr 2009 07:36:00 GMT</pubDate><guid>http://www.aygfsteel.com/sealyu/archive/2009/04/23/267164.html</guid><wfw:comment>http://www.aygfsteel.com/sealyu/comments/267164.html</wfw:comment><comments>http://www.aygfsteel.com/sealyu/archive/2009/04/23/267164.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/sealyu/comments/commentRss/267164.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/sealyu/services/trackbacks/267164.html</trackback:ping><description><![CDATA[<h2>原帖地址Qhttp://odyssi.blogspot.com/2008/01/intro-to-jboss-seam-security-part-1.html</h2> <h3> <a >Intro to JBoss Seam Security, Part 1 - Authentication</a> </h3> <div> <p>Recently, I <a >mentioned</a> how I had just started working with the <a >JBoss Seam application framework</a>. The more I have worked with it, the more impressed I have become at how it makes things that are typically difficult using standard Java EE much simpler and more streamlined. One of the areas in which Seam really shines is security. While Java EE defines <a >JAAS</a> for use in securing applications, it is left up to the developer to ingrain this security down to each facet of the application. With Seam, it is easy to define security constraints at all levels of an application, simply through using annotations. In addition, the complexity of authenticating users with JAAS is reduced through Seam's <a >authenticator</a> mechanism. This article will give an introduction to Seam authentication, and show how to write your own custom authenticator.<br /> <br /> Seam's authenticator construct hides the complexity of managing a JAAS configuration, and allows you to implement authentication how you see fit. Perhaps your organization relies on a simple username/password combination for authenticating user accounts in LDAP. Maybe you use a SecureID token, and the accounts are stored in a SQL database. By writing your own authenticator class, or making use of publicly available ones, you can control the way authentication is done in your organization.<br /> <br /> To get started with your own authenticator, you must first declare it in the <span style="font-size: 85%;"><span style="font-family: courier new;">components.xml</span></span> file. This file manages much of the configuration for Seam. To add your authenticator, you simply define the class and method that will be used for authentication. For example:<br /> <br /> </p> <div> <div> <div><a onclick="dp.sh.Toolbar.Command('ViewSource',this);return false;">view plain</a><a onclick="dp.sh.Toolbar.Command('PrintSource',this);return false;">print</a><a onclick="dp.sh.Toolbar.Command('About',this);return false;">?</a></div> </div> <ol start="1"> <li><components xmlns="http://jboss.com/products/seam/components"  </li> <li>     xmlns:core="http://jboss.com/products/seam/core"  </li> <li>     xmlns:security="http://jboss.com/products/seam/security"  </li> <li>     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  </li> <li>     xsi:schemaLocation=  </li> <li>         "http://jboss.com/products/seam/components http://jboss.com/products/seam/components-2.0.xsd  </li> <li>          http://jboss.com/products/seam/security http://jboss.com/products/seam/security-2.0.xsd">           </li> <li>  </li> <li><security:identity method="#{authenticator.authenticate}">  </li> <li>  </li> <li></components>  </li> </ol> </div> <br /> <br /> You'll notice the #{} syntax used here. This is JBoss' expression language pointing to a class with the instance name of <span style="font-size: 85%;"><span style="font-family: courier new;">authenticator</span></span>, where the <span style="font-size: 85%;"><span style="font-family: courier new;">authenticate</span></span> method will be used to login a user. Now that we have declared an authenticator to Seam, we're ready to implement it. Our example will be quite simple. If the user enters a username of <span style="font-size: 85%;"><span style="font-family: courier new;">admin</span></span>, with a password of <span style="font-size: 85%;"><span style="font-family: courier new;">password</span></span>, they will be authenticated successfully. In addition, we will assign them to the role of <span style="font-size: 85%;"><span style="font-family: courier new;">admin</span></span>, so that they can perform some sort of administrative function within our application. The implementation of our authenticator would look like this:<br /> <br /> <div> <div> <div><a onclick="dp.sh.Toolbar.Command('ViewSource',this);return false;">view plain</a><a onclick="dp.sh.Toolbar.Command('PrintSource',this);return false;">print</a><a onclick="dp.sh.Toolbar.Command('About',this);return false;">?</a></div> </div> <ol start="1"> <li>@Name("authenticator")  </li> <li>public class Authenticator {  </li> <li>  </li> <li>private static final String valid_user = "admin";  </li> <li>private static final String valid_password = "password";  </li> <li>  </li> <li>public boolean authenticate() {  </li> <li>String username = Identity.instance().getUsername();  </li> <li>String password = Identity.instance().getPassword();  </li> <li>  </li> <li>if((username.equals(valid_user)) && (password.equals(valid_password))) {  </li> <li>     return true;  </li> <li>}  </li> <li>  </li> <li>return false;  </li> <li>}  </li> <li>  </li> <li>}  </li> </ol> </div> Our example is rather trivial. However, it gives a slight glimpse into how Seam authentication works. The first thing that you should notice is the <span style="font-size: 85%;"><span style="font-family: courier new;">@Name</span></span> annotation. This annotation prompts Seam to create a bean with the name specified in the annotation. In this case, the name is <span style="font-size: 85%;"><span style="font-family: courier new;">authenticator</span></span>, which is how we arrive at the value specified in our <span style="font-size: 85%;"><span style="font-family: courier new;">components.xml</span></span> file. Our <span style="font-size: 85%;"><span style="font-family: courier new;">authenticate </span></span>method will return <span style="font-size: 85%;"><span style="font-family: courier new;">true </span></span>if authentication was successful, and <span style="font-size: 85%;"><span style="font-family: courier new;">false </span></span>otherwise.<br /> <br /> So how does the authenticate method get the username and password? This is done via the Identity class. The standard <span style="font-size: 85%;"><a style="font-family: courier new;" >Identity</a></span> class that comes with Seam is quite extensive, but basically provides support for a username/password combination. It is possible to subclass <span style="font-size: 85%;"><span style="font-family: courier new;">Identity</span></span>, however, to support whatever authentication mechanisms you may need. You could implement code to support getting a SecureID token value from a user, or a SPNEGO ticket. All that is needed to make use of the <span style="font-size: 85%;"><span style="font-family: courier new;">Identity </span></span>subclass is to add the following annotations to your implementation:<br /> <br /> <div> <div> <div><a onclick="dp.sh.Toolbar.Command('ViewSource',this);return false;">view plain</a><a onclick="dp.sh.Toolbar.Command('PrintSource',this);return false;">print</a><a onclick="dp.sh.Toolbar.Command('About',this);return false;">?</a></div> </div> <ol start="1"> <li>@Name("org.jboss.seam.security.identity")  </li> <li>@Scope(SESSION)  </li> <li>@Install(precedence = APPLICATION)  </li> <li>@BypassInterceptors  </li> <li>@Startup  </li> <li>public class MyCustomIdentity extends Identity  </li> <li>{ ... }  </li> </ol> </div> <br /> Your custom <span style="font-size: 85%;"><span style="font-family: courier new;">Identity </span></span>subclass is now ready for use.<br /> <br /> Now that we have our authentication classes in place, we are ready to create our login form. This is trivial to create using Seam, particularly because of Seam's use of the JBoss expression language in forms. Our login form fragment would look like the following:<br /> <br /> <div> <div> <div><a onclick="dp.sh.Toolbar.Command('ViewSource',this);return false;">view plain</a><a onclick="dp.sh.Toolbar.Command('PrintSource',this);return false;">print</a><a onclick="dp.sh.Toolbar.Command('About',this);return false;">?</a></div> </div> <ol start="1"> <li><div>  </li> <li>   <h:outputlabel for="name" value="Username">  </li> <li>   <h:inputtext id="name" value="#{identity.username}">  </li> <li></div>  </li> <li>  </li> <li><div>  </li> <li>   <h:outputlabel for="password" value="Password">  </li> <li>   <h:inputsecret id="password" value="#{identity.password}">  </li> <li></div>  </li> <li>  </li> <li><div>  </li> <li>   <h:commandbutton value="Login" action="#{identity.login}">  </li> <li></div>  </li> </ol> </div> <br /> <br /> That's all there is to it. You are now ready to authenticate users via your own custom login form and authenticator. While this is an introduction to the simplified form of authentication in Seam, it should give you a good foundation to learn and explore on your own.<br /> <br /> Next time, we will look at how authentication is used throughout an application, not just at the entry point. </div> <p post-footer-line-1=""><span> Posted by WhoAmI? </span> <span> at <a title="permanent link">11:59 AM</a> </span> <span> <span> <a title="Email Post">   </a> </span> <span blog-admin="" pid-277683962=""> <a title="Edit Post"> <img alt="" class="icon-action" src="http://www.blogger.com/img/icon18_edit_allbkg.gif" height="18" width="18" /> </a> </span> </span> </p> <img src ="http://www.aygfsteel.com/sealyu/aggbug/267164.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/sealyu/" target="_blank">seal</a> 2009-04-23 15:36 <a href="http://www.aygfsteel.com/sealyu/archive/2009/04/23/267164.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Seam中配|事务管理器QConfiguring a Seam transaction managerQ?/title><link>http://www.aygfsteel.com/sealyu/archive/2009/04/20/266600.html</link><dc:creator>seal</dc:creator><author>seal</author><pubDate>Mon, 20 Apr 2009 12:10:00 GMT</pubDate><guid>http://www.aygfsteel.com/sealyu/archive/2009/04/20/266600.html</guid><wfw:comment>http://www.aygfsteel.com/sealyu/comments/266600.html</wfw:comment><comments>http://www.aygfsteel.com/sealyu/archive/2009/04/20/266600.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/sealyu/comments/commentRss/266600.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/sealyu/services/trackbacks/266600.html</trackback:ping><description><![CDATA[原帖地址Qhttp://www.redhat.com/docs/en-US/JBoss_Enterprise_Application_Platform/4.3.0.cp04_fp01/html/Seam_Reference_Guide/ch10s02s02.html<br /> <br /> <h3 id="d0e8114">Configuring a Seam transaction manager</h3> <div> Seam provides a transaction management abstraction for beginning, committing, rolling back, and synchronizing with a transaction. By default Seam uses a JTA transaction component that integrates with Container Managed and programmatic EJB transactions. If you are working in a Java EE 5 environment, you should install the EJB synchronization component in <code>components.xml</code>: </div> <pre xml=""><transaction:ejb-transaction /><br /> </pre> <div> However, if you are working in a non EE 5 container, Seam will try auto detect the transaction synchronization mechanism to use. However, if Seam is unable to detect the correct transaction synchronization to use, you may find you need configure one of the following: </div> <div> <ul> <li> <div> JPA RESOURCE_LOCAL transactions with the <code>javax.persistence.EntityTransaction</code> interface. <code>EntityTransaction</code> begins the transaction at the beginning of the apply request values phase. </div> </li> <li> <div> Hibernate managed transactions with the <code>org.hibernate.Transaction</code> interface. <code>HibernateTransaction</code> begins the transaction at the beginning of the apply request values phase. </div> </li> <li> <div> Spring managed transactions with the <code>org.springframework.transaction.PlatformTransactionManager</code> interface. The Spring <code>PlatformTransactionManagement</code> manager may begin the transaction at the beginning of the apply request values phase if the <code>userConversationContext</code> attribute is set. </div> </li> <li> <div> Explicitly disable Seam managed transactions </div> </li> </ul> </div> <div> Configure JPA RESOURCE_LOCAL transaction management by adding the following to your components.xml where <code>#{em}</code> is the name of the <code>persistence:managed-persistence-context</code> component. If your managed persistence context is named <code>entityManager</code>, you can opt to leave out the <code>entity-manager</code> attribute. (see <a title="10.3. Seam-managed persistence contexts">Section 10.3, “Seam-managed persistence contexts”</a>Seam-managed persistence contexts) </div> <pre xml=""><transaction:entity-transaction entity-manager="#{em}"/><br /> </pre> <div> To configure Hibernate managed transactions declare the following in your components.xml where <code>#{hibernateSession}</code> is the name of the project's <code>persistence:managed-hibernate-session</code> component. If your managed hibernate session is named <code>session</code>, you can opt to leave out the <code>session</code> attribute. (see <a title="10.3. Seam-managed persistence contexts">Section 10.3, “Seam-managed persistence contexts”</a>Seam-managed persistence contexts) </div> <pre xml=""><transaction:hibernate-transaction session="#{hibernateSession}"/><br /> </pre> <div> To explicitly disable Seam managed transactions declare the following in your components.xml: </div> <pre xml=""><transaction:no-transaction /><br /> </pre> <div> For configuring Spring managed transactions see <a title="24.5. Using Spring PlatformTransactionManagement">Section 24.5, “Using Spring PlatformTransactionManagement”</a>using Spring PlatformTransactionManagement. . </div> <br /> <img src ="http://www.aygfsteel.com/sealyu/aggbug/266600.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/sealyu/" target="_blank">seal</a> 2009-04-20 20:10 <a href="http://www.aygfsteel.com/sealyu/archive/2009/04/20/266600.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JSF Validator(?http://www.aygfsteel.com/sealyu/archive/2009/04/14/265446.htmlsealsealTue, 14 Apr 2009 02:58:00 GMThttp://www.aygfsteel.com/sealyu/archive/2009/04/14/265446.htmlhttp://www.aygfsteel.com/sealyu/comments/265446.htmlhttp://www.aygfsteel.com/sealyu/archive/2009/04/14/265446.html#Feedback0http://www.aygfsteel.com/sealyu/comments/commentRss/265446.htmlhttp://www.aygfsteel.com/sealyu/services/trackbacks/265446.htmlJSF Validator入门基础?- JSF Validator的介l与使用

JSF框架提供Validator机制Q对用户输入值的合法性进行验证。若用户输入值无效,q提供了错误消息昄功能Q以帮助用户能正输入?/span>

在开始本文之前,阅读下面的文章:
深入了解JSF
深入了解JSFQ二Q:从JSF的Lifecycle看JSF寚w面的处理机制和流E?/strong>
以了解JSF的概늭?br />
JSF Validator图:


JSF Validator特点Q?/div> 输入数据的验证放在服务器端进行?br /> 需要验证输入值的lgQ输入组Ӟ在JSP里通过JSF标签加以讄Q方法简单直观?br /> 每个输入lg可以同时l定多个Validator?br /> 验证发生错误Ӟ可以向FacesContextd错误信息Qƈ且可以通过JSP直接昄。显C风g位置可以自由讑֮?br /> 验证错误ӞJSF的生命周期控制机制自动中止处理流E,跌{到画面描画阶D(Render Response PhaseQ?br /> JSF标准提供Ҏ|long, doubleQ的最大最值验证,文字列的最大最长度验证,以及必须(required)验证{Validator?br /> 支持用户自定义Validator。用戯定义Validator的方法有2U,一U是Method ValidatorQ一U是实现javax.faces.validator.Validator接口。本文的后面对其作详细介绍?br />

JSF标准Validator

validateDoubleRange


Validator标签名:f:validateDoubleRange标签?br />   属性名Q?br />       maximum="最大?
      minimum="最?
Validator IDQjavax.faces.DoubleRange
Validator c:javax.faces.validator.DoubleRangeValidator
输入值的范围验证?br /> 输入值必MؓNumberQ数|cd或者可以{换ؓDoublecd的?br />

validateLongRange


Validator标签名:f:validateLongRange
  属性名Q?br />       maximum="最大?
      minimum="最?
Validator IDQjavax.faces.LongRange
Validator c:javax.faces.validator.LongRangeValidator
输入值的范围验证?br /> 输入值必MؓNumberQ数|cd或者可以{换ؓLongcd的?br />

validateLength


Validator标签名:f:validateLength
  属性名Q?br />       maximum="最大?
      minimum="最?
Validator IDQjavax.faces.Length
Validator c:javax.faces.validator.LengthValidator
输入值的长度验证?br /> 输入值必MؓStringQ字W串Q或者可以{换ؓStringcd的?br />

JSF requiredQ必输入) Validator
JSF的几个输入组件还可以使用required属性简单地验证表单元素是否得到输入?br /> <h:inputHidden required="true/false"></h:inputHidden>
<h:inputSecret required=“true/false”></h:inputSecret>
<h:inputText required=“true/false”></h:inputText>
<h:inputTextarea required=“true/false”></h:inputTextarea>

<h:selectBooleanCheckbox required=“true/false”></h:selectBooleanCheckbox>
<h:selectManyCheckbox required=“true/false”></h:selectManyCheckbox>
<h:selectManyListbox required=“true/false”></h:selectManyListbox>
<h:selectManyMenu required=“true/false”></h:selectManyMenu>
<h:selectOneListbox required=“true/false”></h:selectOneListbox>
<h:selectOneMenu required=“true/false”></h:selectOneMenu>
<h:selectOneRadio required=“true/false”></h:selectOneRadio>

JSF Validator的?/div> 各输入组件用required validator的方法上面已l作了介l,q里不再重复?br />

使用Method Validator


JSF支持MethodU别的ValidatorQ这UValidator实现h比较单,可以在Q何JSF的managed-bean里实C个类g下的ҎQ?br />
  1. public void validateXxxx(FacesContext context,   
  2.         UIComponent component, Object value){  
  3.   
  4.     String text = value.toString();  
  5.     if(!text.equals("xxxx")){  
  6.         throw new ValidatorException(new FacesMessage("some message"));  
  7.     }  
  8. }  

其中Qcontext变量为JSF容器上下文环境,component? l定的组Ӟvalue为组件的输入倹{validateXxxx可以ZQ意你喜欢的方法名。与预期的输入gW合的话Q可以通过throw一? ValidatorException?some message"便是惌昄的错误消息?br />
然后在JSP中:
  1. <h:inputText value="#{mybean.someValue}" validator="#{mybean.validateXxxx}"/>  

便可?br /> 错误消息的显C稍后再作介l?br />

Validator标签的?/h3>
Validator标签可以接收参数Q所以功能上比较强大Q也比较灉|。同Ӟ除了使用JSF标准的Validator标签之外Q你q可以自定义Validator标签。关于自定义Validator标签我们在另外的文章中加以介绍?br /> Validator标签的用例Q?br />
  1. <h:inputText id="xxxxValue" value="#{mybean.xxxxValue}" required="true">  
  2.  <f:validateDoubleRange maximum="5"></f:validateDoubleRange>  
  3. </h:inputText>  
  4. <h:message for="xxxxValue"></h:message>  

? 例对id为xxxxValue的输入框lg的输入值做double范围验证Q指定范围最大gؓ5。超q?的情况则昄错误消息Q错误消息可以 ?lt;h:message />或?lt;h:messages />标签昄。有x息处理的详细介绍请参考:
JSF全面理解之消息处?/strong>
一?br />

f:validator标签的用与Validator ID


除了以上2U验证方法之外,q可以用f:validator标签对输入值加以验证。f:validator标签需要指定validatorId属性,Validator Id需要在faces-config.xml配置文g中加以配|?br />

f:validator标签的用例Q?br />
  1. <h:inputText id="xxxxValue" value="#{mybean.xxxxValue}" required="true">  
  2.   <f:validator validatorId="Some Validator ID"></f:validator>  
  3. </h:inputText>  

"Some Validator ID"为具体的Validator IDQ我们将在自定义Validator标签一文中对Validator ID做详l介l?br />
JSF框架调用指定Validator ID所对应的Validator?br /> public void validate(FacesContext context, UIComponent component, Object value)
Ҏ?br />
跟Method Validator一P不能f:validator标签传入参数?br />
本文介绍了JSF Validator的机Ӟ特点Q种c,以及使用Ҏ{。我们将在近期其它文章中介绍怎么自定义Validator?br />

JSF Validatorq阶?- 自定义JSF Validator


JSF框架提供Validator机制Q对用户输入值的合法性进行验证。若用户输入值无效,q提供了错误消息昄功能Q以帮助用户能正输入?/span>


?JSF Validator入门基础?- JSF Validator的介l与使用  一文中我们介绍了JSF Validator的机Ӟ特点Q种c,以及使用Ҏ{?br />
本文介l怎么自定义Validator和Validator标签?br />
自定义Validator?U方法:一U是Method ValidatorQ我们在JSF Validator入门基础?- JSF Validator的介l与使用  一文中已作了介l,q里不再详述Q另一U是通过实现Validator接口Q也是使用自定义的ValidatorcR?br />
自定义ValidatorcMValidator标签有以下几个步骤:
自定义Validatorcȝ实现
faces-config.xmld
自定义Validator标签c?br /> 讄TLD文g


自定义Validatorcȝ实现
定义一个类Q该cd现javax.faces.validator.Validaotr接口Q?br />
MyValidator.java
  1. package com.mypackages;  
  2.   
  3. import javax.faces.validator.Validaotr;  
  4.   
  5. public class MyValidator implements Validator {  
  6.     public void validate(FacesContext context, UIComponent component, Object value)  
  7.             throws ValidatorException {  
  8.   
  9.         String text = value.toString();  
  10.         if(!text.equals("xxxx")){  
  11.             throw new ValidatorException(new FacesMessage("some message"));  
  12.         }  
  13.     }  
  14.   
  15.     ... //其它参数讄Q方法等Q略Q?nbsp; 
  16. }  


faces-config.xmld
自定义ValidatorcM后,q得向faces-config.xmld之后才能使用?br /> faces-config.xml
  1. <?xml version="1.0"?>  
  2. <!DOCTYPE faces-config PUBLIC  
  3.   "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.0//EN"  
  4.   "http://java.sun.com/dtd/web-facesconfig_1_0.dtd">  
  5.   
  6.   
  7. <faces-config xmlns="http://java.sun.com/JSF/Configuration">  
  8.     <validator>  
  9.         <validator-id>MyValidator</validator-id>  
  10.         <validator-class>com.mypackages.MyValidator</validator-class>  
  11.     </validator>  
  12. </faces-config>  


l过上面2个步骤,可以用MyValidator了?br /> 例:
<h:inputText id="xxxxValue" value="#{mybean.xxxxValue}">
  <f:validator validatorId="MyValidator"></f:validator>
</h:inputText>

自定义Validator标签c?/div> 上面的MyValidator虽然可以通过f:validator标签加以利用Q?但不能向其传入参敎ͼ若要向其传入参数Q则需要定义自定义Validator标签cR?br /> MyValidatorTag.java
  1. package com.mypackages;  
  2.   
  3. import javax.faces.webapp.ValidatorTag;  
  4.   
  5. public class MyValidatorTag extends ValidatorTag{  
  6.   
  7.     private String xxxParam;  
  8.       
  9.     public MyValidatorTag(){  
  10.         setValidatorId("MyValidator");  
  11.     }  
  12.       
  13.     protected Validator createValidator() throws JspException {  
  14.         MyValidator validator =  (MyValidator)super.createValidator();  
  15.         validator.setXxxParam(xxxParam);  
  16.         return validator;  
  17.     }  
  18.   
  19.     public String getXxxParam() {  
  20.         return xxxParam;  
  21.     }  
  22.   
  23.     public void setXxxParam(String xxxParam) {  
  24.         this.xxxParam = xxxParam;  
  25.     }  
  26. }  

另外QؓMyValidator.java加入相应参数及方法实现?br />
TLD文g
定义好Validator标签cM后,q需要在TLD文g讄Q有关TLDq里׃介绍了。请大家参考相兌料?br />
MyValidator.tld
  1. <?xml version="1.0" encoding="ISO-8859-1" ?>  
  2. <!DOCTYPE taglib  
  3.   PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"  
  4.   "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">  
  5. <taglib xmlns="http://java.sun.com/JSP/TagLibraryDescriptor">  
  6.     <tlib-version>1.0</tlib-version>  
  7.     <jsp-version>1.2</jsp-version>  
  8.     <short-name>myv</short-name>  
  9.     <uri>my validator tag</uri>  
  10.     <display-name>my validator tag</display-name>  
  11.   
  12.     <tag>  
  13.         <name>validateMyData</name>  
  14.         <tag-class>com.mypackages.MyValidatorTag</tag-class>  
  15.         <attribute>  
  16.             <name>xxxParam</name>  
  17.             <required>false</required>  
  18.         </attribute>  
  19.     </tag>  
  20. </taglib>  


自定义Validator标签的?/div> web.xml
  1.  <taglib>  
  2.   <taglib-uri>/WEB-INF/MyValidator.tld</taglib-uri>  
  3.   <taglib-location>/WEB-INF/MyValidator.tld</taglib-location>  
  4.  </taglib>  



JSP
  1. <%@ taglib uri="WEB-INF/MyValidator.tld" prefix="myv" %>  
  2.   
  3. ...  
  4.   
  5. <h:inputText value="#{mybean.xxxxValue}">  
  6.     <myv:validateMyData xxxParam="Some Parameter"/>  
  7. </h:inputText>  



seal 2009-04-14 10:58 发表评论
]]>EntityManager:seam新手必读Q{Q?/title><link>http://www.aygfsteel.com/sealyu/archive/2009/04/13/265298.html</link><dc:creator>seal</dc:creator><author>seal</author><pubDate>Mon, 13 Apr 2009 07:34:00 GMT</pubDate><guid>http://www.aygfsteel.com/sealyu/archive/2009/04/13/265298.html</guid><wfw:comment>http://www.aygfsteel.com/sealyu/comments/265298.html</wfw:comment><comments>http://www.aygfsteel.com/sealyu/archive/2009/04/13/265298.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/sealyu/comments/commentRss/265298.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/sealyu/services/trackbacks/265298.html</trackback:ping><description><![CDATA[ 原帖地址Qhttp://blog.csdn.net/bq_cui/archive/2007/03/21/1536706.aspx<br /> <br /> 开始学习seam的时候,有两个问题:我会用Spring和HibernateQ但一点也不懂Seam 和EJB3?EntityManager。我用了一些时间学习seamQ但EntityManager 一直困扰我?span><br />     同时我也有了一些小收获Q愿意跟刚刚开始学习seam的朋友分享以下。别紧张Q我不敢信我写的东襉K正确 ;). <br />     好了Q关于EntityManager有何用处Q它理你的entities ;)?那是一些简单的java对象Q通过getters and setters具备一些属性。这些属性之一是idQ一般是Long数据cdQ,q且q些class必须以@Entity注解(annotated )。在seam的源码中可以扑ֈ一大批q样的例子,例如booking例子。在seam中,一件很重要的事情就是,每个Entity都有一? @Name 注解(annotation)Q这P它们才能被注入到其他seam部g(component)中?br /> </span>    假设我们有这样一个entity classQ叫?Entity"。其生命周期内包含以下功能: <p dir="ltr" style="margin-right: 0px;">?/p> <p dir="ltr" style="margin-right: 0px;">?/p> <p dir="ltr" style="margin-right: 0px;">?/p> <p dir="ltr" style="margin-right: 0px;">?/p> <p dir="ltr" style="margin-right: 0px;">EntityManager 提供了这些功能。首先,如何把EntityManager 引入我的代码Q很单:</p> <span> <div style="border: 0.5pt solid windowtext; padding: 4px 5.4pt; background: #e6e6e6 none repeat scroll 0% 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; width: 95%;"> <div><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><span style="color: #000000;">@PersistenceContext<br /> <img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /></span><span style="color: #0000ff;">private</span><span style="color: #000000;"> EntityManager em;    </span></div> </div> <p dir="ltr" style="margin-right: 0px;">    好了Q我们看看一个Entity q程如何产生Q?/p> <div style="border: 0.5pt solid windowtext; padding: 4px 5.4pt; background: #e6e6e6 none repeat scroll 0% 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; width: 95%;"> <div><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><span style="color: #000000;">Entity entity </span><span style="color: #000000;">=</span> <span style="color: #0000ff;">new</span><span style="color: #000000;"> Entity();    </span></div> </div> <p dir="ltr" style="margin-right: 0px;">    q很单。现在,qentity 的状态是<span style="font-weight: bold;">NEW/TRANSIENT 。这意味着一个entity已经存在于你的应用程序中Q但q不hidQ也不存在于你的数据库中?br /> <br />     ׃我们要它持久化Q即它应被写入数据库Q,我们应把它的状态{换ؓ<span style="font-weight: bold;">MANAGED</span> ?/span></p> <div style="border: 0.5pt solid windowtext; padding: 4px 5.4pt; background: #e6e6e6 none repeat scroll 0% 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; width: 95%;"> <div><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><span style="color: #000000;">em.persist(entity);    </span></div> </div> <p>    现在Q此entity由EntityManager理了。EntityManager控制entity写入数据库。这动作无须立刻发生Q可能把你的entity攑֜cacheQ稍后写入数据库。你可以攑ֿQ写动作肯定会发生?br /> <br /> Ok, what about reading an existing entity from the database? Therefore we use: </p> <p>好,如何从数据库中读出已存在的entity呢?q样Q?/p> <div style="border: 0.5pt solid windowtext; padding: 4px 5.4pt; background: #e6e6e6 none repeat scroll 0% 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; width: 95%;"> <div><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><span style="color: #000000;">Entity entity </span><span style="color: #000000;">=</span><span style="color: #000000;"> em.find(Entity.</span><span style="color: #0000ff;">class</span><span style="color: #000000;">, Id);    </span></div> </div> <p>    每个entity 有一个idQ我已经说过Q多数情况下是Long数据cdQ,通过id你可存取entity。这是这里的W二个参数。第一个参C表你要存取的Entity class的进E。find操作之后Qentity的状态也?span style="font-weight: bold;">MANAGED ?/span></p> <p>一旦entity数据有所改变Q将反映到数据库中。不能确认EntityManager何时会向数据库写入更新的数据。但是这一事g肯定会发生,一般是马上Q但不会晚于EntityManager消失<span>;)。你可以控制触发更新数据库:<br /> <br /> <div style="border: 0.5pt solid windowtext; padding: 4px 5.4pt; background: #e6e6e6 none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; width: 95%;"> <div><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><span style="color: #000000;">em.flush();    </span></div> </div> <br /> </span>     q将强制EntityManager 立刻更新写入数据库。请CQ这条语句将影响所有状态ؓ<span style="font-weight: bold;">MANAGED?/span>entitieQ而不是当前一个。不q,一般情况下不必q么做?br />     如果你想反其道而行之,也就是从数据库蝲入一?span>entity Q因为别人可能已l修改其数据Q,q么写:<br /> <div style="border: 0.5pt solid windowtext; padding: 4px 5.4pt; background: #e6e6e6 none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; width: 95%;"> <div><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><span style="color: #000000;">em.refresh(entity);    </span></div> </div> <br /> </span><span>    怎样删除一个entity呢?很简单:<br /> <div style="border: 0.5pt solid windowtext; padding: 4px 5.4pt; background: #e6e6e6 none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; width: 95%;"> <div><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><span style="color: #000000;">em.remove(entity);    </span></div> </div> <br /> </span>    现在Qentity的状态成?span style="font-weight: bold;">REMOVEDQ表C其已经被列入删除计划。你可以?/span>flush()语句Q让删除动作马上发生Q但没必要这么干?br /> <br />     现在来点复杂的。当注入EntityManager 的时候,有一?span style="font-weight: bold;">事务范围持久上下文(</span><span style="font-weight: bold;"> Transaction Scoped Persistence Context</span>Q。当entitie处在MANAGED状态时Q其处在持久上下文(persistence context Q的“容器”中?#8220;事务范围”意味什么?首先Q什么是“事务”Q?br /> <br />     EJB3Stateful ?Stateless beans (依同名标注L?的每个方法调用都包装C个事务内。(Z说一下,事务一旦发生RuntimeExceptionQ即发生会滚Q对数据的改变将撤销Q。因此,持久上下文(persistence contextQ将在调用方式之前徏立,方式调用l束后移除。然后,持久上下文中理的所有entity的状态成?span style="font-weight: bold;"> DETACHED?/span><br /> <br />     假设在你的bean里头有两个method。第一个是load(), 它调用find函数取出数据库中的一个实体。第二个是finish()Q返回一个JSF输出。调用这两个函数中间修改了实体数据。这U修Ҏ久到数据库中吗?回答是:NO?br /> <br />     load() 函数l束后,EntityManager'的持久上下文l束Q它所有管理过的entity状态成为DETACHED。一个后果是Q与新entity相反-有一个IDQ但他们的状态ƈ不是managed Q对q些detached entities 所作的更新q不影响数据库。如果你想一个entity 更新数据库,需要将光新attach到持久上下文。在q个例子中,?span>finish()Ҏ中增加以下行Q?br /> <div style="border: 0.5pt solid windowtext; padding: 4px 5.4pt; background: #e6e6e6 none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; width: 95%;"> <div><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><span style="color: #000000;">em.merge(entity);    </span></div> </div> </span><br />     现在q个entity 已经合ƈ到finish()Ҏ的持久上下文?CQ每个方法是一个事务,每个事物有自q持久上下?Qƈ且状态是又变为managed?br /> <br />      q样做是可以的,但有两个~点Q?br /> -需要调用merge(->多了一些代?<br /> -调用find()之前Q如果某个entity未初始化Q而你又要存取它的某些属性,会得到exception 错误?br /> <br />     有一个简单的解决ҎQ扩展持久上下文的生命期Q这P当调用多个事?ҎӞentity状态始l保持ؓmanaged 。因此,我们改变EntityManager的注入方式:<br /> <span> <div style="border: 0.5pt solid windowtext; padding: 4px 5.4pt; background: #e6e6e6 none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; width: 95%;"> <div><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><span style="color: #000000;">@PersistenceContext(type</span><span style="color: #000000;">=</span><span style="color: #000000;">PersistenceContextType.EXTENDED<br /> <img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /></span><span style="color: #0000ff;">private</span><span style="color: #000000;"> EntityManager em;    </span></div> </div> </span><br />      现在Qmanaged entities "生活?一个扩展持久上下文? <span style="font-weight: bold;">Extended Persistence Context </span>)?br /> <br />     你甚xd叫merge()ҎQ因为eitities从未被DETACHED。你可能会问Q普通事务范_ "normal" (transaction scoped) Q持久上下文的好处是什么?它一直依附于你做的事情(崔Q什么意思?Q。扩展上下文需要更多的内存Q因为即使你不需要,它也一直存在于内存。ƈ且一旦entities被其他的bean改变Q它们有自己的持久上下文Q,你需要显式地调用refresh()ҎQ在overviews/list面Q。当你需要普通EntityManager 时它在那里Q因其生命周期短Q只能操作即时数?) <br /> <span>    <br />     当谈及列表:为取得不止一个实体,而是一个实体集合,使用Q?br /> <div style="border: 0.5pt solid windowtext; padding: 4px 5.4pt; background: #e6e6e6 none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; width: 95%;"> <div><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><span style="color: #000000;">List</span><span style="color: #000000;"><</span><span style="color: #000000;">Entity</span><span style="color: #000000;">></span><span style="color: #000000;"> entities </span><span style="color: #000000;">=</span><span style="color: #000000;"> em.createQuery(</span><span style="color: #000000;">"</span><span style="color: #000000;">from Entity</span><span style="color: #000000;">"</span><span style="color: #000000;">).getResultList();    </span></div> </div> </span><br />     q不?#8220;真正”SQLQ而是cMsql的东西,UC?span>EJBQL。你可以用它执行某些条g查询Q排序等Q如<br /> <div style="border: 0.5pt solid windowtext; padding: 4px 5.4pt; background: #e6e6e6 none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; width: 95%;"> <div><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><span style="color: #000000;">...</span><span style="color: #000000;">"</span><span style="color: #000000;">from Entity where lastName=</span><span style="color: #000000;">"</span><span style="color: #000000;">.nameToSearchFor.</span><span style="color: #000000;">"</span><span style="color: #000000;"> order by firstName</span><span style="color: #000000;">"</span><span style="color: #000000;">    </span></div> </div> <br /> </span>    仅用entity属性名U即可。关于EJBQL 要说的太多了Q但对于本篇介绍来说q已_?br /> <br />     好,基本介绍到此为止。希望对你来_在如何用EntityManager斚wQ这一个简单易懂的介绍?br /> <br />     我已声明q,不能保证癑ֈ百正。ƈ且肯定有许多p语法错误(对不P我是德国人,不要打我PP?。欢q斧正?br /> <br /> <br /> 2007.4.11译自:<br /> http://www.jboss.com/index.html?module=bb&op=viewtopic&t=88460</p> </span> <img src ="http://www.aygfsteel.com/sealyu/aggbug/265298.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/sealyu/" target="_blank">seal</a> 2009-04-13 15:34 <a href="http://www.aygfsteel.com/sealyu/archive/2009/04/13/265298.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SEAM中JSTL标签和ui标签的؜合?c:forEach vs ui:repeat)http://www.aygfsteel.com/sealyu/archive/2009/04/13/265212.htmlsealsealMon, 13 Apr 2009 00:52:00 GMThttp://www.aygfsteel.com/sealyu/archive/2009/04/13/265212.htmlhttp://www.aygfsteel.com/sealyu/comments/265212.htmlhttp://www.aygfsteel.com/sealyu/archive/2009/04/13/265212.html#Feedback0http://www.aygfsteel.com/sealyu/comments/commentRss/265212.htmlhttp://www.aygfsteel.com/sealyu/services/trackbacks/265212.htmlc:forEach vs ui:repeat in Facelets

Posted by Roger Keays, 7 June 2007, 12:28 PM

This is probably one of the most frequently asked questions on the Facelets mailing list. Why doesn't my c:forEach tag work correctly? Unfortunately, there are may ways to misuse the jstl tags available in Facelets, so the answer isn't always simple. Here is an explanation of the differences between c:forEach and ui:repeat, along with some examples which will hopefully save you some headaches.

TagHandlers vs Components

The most important thing to understand about the jstl tags in Facelets is that they do not represent components and never become a part of the component tree once the view has been built. Rather, they are tags which are actually responsible for building the tree in the first place. Once they have done their job they expire, are no more, cease to be, etc etc.

Here is a table of the semantics of several common tags. I just discovered, reading the Facelets code, that validators and converters are classified separately. I had always thought they were just tag handlers, but I imagine they behave in much the same way.

TagHandlers
Components
Other

c:forEach
c:choose
c:set
c:if
f:facet
f:actionListener
f:valueChangeListener
ui:include
ui:decorate
ui:composition
any custom tag file

ui:repeat
ui:fragment
ui:component
f:view
f:verbatim
f:selectItems
h:inputText
h:datatable
any custom UIComponent

f:validator
f:converter

One of the problems here is that there is no naming convention to indicate which tags correspond to which constructs. You've just got to know, or find out.

When is the view built?

Now that you understand that tag handlers are only effective when the tree is built, the next logical question should be well, when is tree built?

The short answer is that a new view is built for every request which is not a postback. During a postback, the view is reconstructed from saved state. Quite confusing, and not very obvious I know, but there you have it.

Common laments

The most common pitfalls are either with the JSF lifecycle, EL evaluation or combining tag handlers with components.

My c:if always evaluates to false

<h:dataTable values="${numbers}" var="number">
<h:column>
<c:if test="${number > 5}">
<h:outputText value="${number}"/>
</c:if>
</h:column>
</h:datatable>

Yes, the c:if is always evaluating to false! But it is only ever evaluated once - when the tree is built. The h:outputText component never makes it into the tree. Solution: replace the c:if with:

<ui:fragment rendered="${number > 5}"> ... </ui:fragment>

You could also use the rendered attribute on the h:outputText component in this example.

My ui:include fails inside ui:repeat

<ui:repeat value="#{bean.items}" var="item">
   <ui:include src="#{item.src}"/>
</ui:repeat>

The EL for the ui:include is evaluated when the view is built and is invalid since it relies on a variable only made available by the ui:repeat during rendering. Use c:forEach in this case.

My recursive tag never stops

myTag.xhtml:
<ul>
<ui:repeat value="${item.children} var="child">
<li><eg:myTag item="${child}"/></li>
</ui:repeat>
</ul>

The stop condition in this recursion is supposed to be when you run out of children. The problem is that the custom eg:myTag is just a tag handler, like a special version of ui:include. When the view is built, the ui:repeat has no influence on the building process and can't stop the recursion. Use c:forEach here instead of ui:repeat. Or better still, convert your tag file to a real UIComponent.

You might also recognise that the ${child} EL expression is meaningless during build time in this example, unless you use c:foreach.

My list doesn't change size after deleting or adding an item

<h:form>
<c:forEach items="${list}" var="item">
<h:outputText value="${item.name}"/><br/>
</c:forEach>
<h:commandButton value="Create new item" action="..."/>
<h:commandButton value="Delete an item" action="..."/>
</h:form>

When your view was built you only had, say, 5 items. If you post back to this view and add or delete an item, your view still has 5 h:outputText components in it since it was restored from saved state. In this simple case, you should use ui:repeat and your tree will always contain one h:ouputText component which is iterated over with differing values of ${item}.

If you rely on using c:forEach to dynamically include different form components you could run into difficulty. Always try to think about what the resulting tree looks like and remember it doesn't change on a postback.

Suggestions for the future

Probably the best relief to this problem would be to come up with a better syntax or naming convention to distinguish between tag handlers and components. I imagine you could also improve compilation performance if you did this.

Secondly, we need better terminology. I've used the terms tag handler and component in this blog which isn't too bad. The Facelets' FAQ [1] uses the terms build-time tags and render-time tags which is a bit misleading because render-time tags (components) are involved in all phases of the JSF lifecycle, not just the Render View phase.

Whatever happens, tag handlers are very useful (would you use facelets without ui:decorate?) so let's not get rid of them.

References

[1] http://wiki.java.net/.../FaceletsFAQ#Why_doesn_t_my_c_if_ui_repeat_ui



seal 2009-04-13 08:52 发表评论
]]>Seam?select list的用?/title><link>http://www.aygfsteel.com/sealyu/archive/2009/04/09/264599.html</link><dc:creator>seal</dc:creator><author>seal</author><pubDate>Thu, 09 Apr 2009 02:54:00 GMT</pubDate><guid>http://www.aygfsteel.com/sealyu/archive/2009/04/09/264599.html</guid><wfw:comment>http://www.aygfsteel.com/sealyu/comments/264599.html</wfw:comment><comments>http://www.aygfsteel.com/sealyu/archive/2009/04/09/264599.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/sealyu/comments/commentRss/264599.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/sealyu/services/trackbacks/264599.html</trackback:ping><description><![CDATA[<h2>Selecting from a list of entities </h2> <p>See <a class="external free" title="http://docs.jboss.org/seam/latest/reference/en/html/controls.html" rel="nofollow">http://docs.jboss.org/seam/latest/reference/en/html/controls.html</a> </p> <ul> <li> Use <tt><s:selectItems></tt> to produce a list of labeled select items from a list of entities. </li> <li> Use <tt><s:convertEntity></tt> to map back and forth between the select items and the actual entity values. This is what allows you to map the <tt>value</tt> of the <tt><h:selectOneMenu></tt> directly to the property of the referencing entity (e.g. a property that is a many-to-one). </li> </ul> <pre><h:selectOneMenu value="#{person.continent}" required="true"> (1)<br /> <s:selectItems value="#{continents.resultList}" var="continent" (2)<br /> label="#{continent.name}" noSelectionLabel="Please Select..."/><br /> <s:convertEntity /> (3)<br /> </h:selectOneMenu><br /> </pre> <ol> <li> <tt>person</tt> is an entity that has been outjected into the conversation. It has a 'continent' property which is many-to-one association with another entity. </li> <li> <tt>continents</tt> is a Seam application framework 'query' object. This 'query' object should probably use a Seam-managed EntityManager because we want have the Hibernate <a title="Session-in-view with Seam">session-in-view behavior</a> so we don't get lazy initialization exceptions when rendering the labels, etc. </li> <li> <tt>s:convertEntity</tt> will convert the Continent entities into values for the HTML select, and vice versa. </li> </ol> <h3> Tips </h3> <ol> <li> To avoid LazyInitializationExceptions and/or writing extra code in your EJB/Controller bean to initialize objects, use <a title="Session-in-view with Seam">session in view</a>. </li> <li> For required fields, put <tt>required="true"</tt> on the <tt>selectOneMenu</tt> and override <tt>javax.faces.component.UIInput.REQUIRED</tt> in <tt>messages.properties</tt> (see <a title="Standard Faces Error Messages">Standard Faces Error Messages</a>). </li> </ol> <h2> Select from an enum </h2> <p>This works just like selecting an entity, but <tt><s:convertEnum/></tt> is used instead. </p> <p><br /> XHTML: </p> <pre><h:selectOneMenu id="marketStatus" value="#{person.status}" (1)<br /> required="true"><br /> <s:selectItems value="#{enumLists.statusArray}" var="status" (2)<br /> label="#{status}"<br /> noSelectionLabel="Select a status..."/><br /> <s:convertEnum/><br /> </h:selectOneMenu><br /> </pre> <p>EnumLists.java: </p> <pre>@Name("enumLists")<br /> @Scope(ScopeType.STATELESS)<br /> public class EnumLists<br /> {<br /> public Status[] getStatusArray()<br /> {<br /> return Status.values();<br /> }<br /> }<br /> </pre> <ol> <li> <tt>person</tt> is an entity that has been outjected into the conversation. It has a 'status' property which is an enum. </li> <li> We need to expose the values of the enum as a list or an array, so we make a stateless POJO component with getters that returns arrays for various enums called <tt>enumLists</tt>. </li> </ol> <h2> Multi-select from an enum </h2> <p>Here we use a <a class="external text" title="http://www.exadel.com/tutorial/jsf/jsftags-guide.html#selectmany" rel="nofollow">selectManyCheckbox</a>. </p> <p><br /> </p> <pre><h:selectManyCheckbox id="roles" <br /> layout="pageDirection" value="#{person.roles}"<br /> required="true"><br /> <s:selectItems value="#{enumLists.roleArray}" var="role"<br /> label="#{role}"/><br /> <s:convertEnum/><br /> </h:selectManyCheckbox><br /> </pre> <p>Unfortunately, Seam's <tt>convertEnum</tt> can't handle multi selects yet. This example will yeild a strange exception: </p> <pre>java.lang.IllegalArgumentException: java.util.List is not an enum type<br /> </pre> <p>Luckily, it's very easy to create <a title="Custom converter tags with Facelets">custom converter tags with Facelets</a>. Here is the converter class that handles both ordinary enums and multi-selects: </p> <pre>package eg;<br /> <br /> import javax.faces.component.*;<br /> import javax.faces.context.*;<br /> import javax.faces.convert.*;<br /> import javax.faces.el.ValueBinding;<br /> import java.util.List;<br /> import java.util.Collection;<br /> <br /> /**<br /> * Converter for enum multi-selects.<br /> * <br>User: Joshua Davis<br /> * Date: May 16, 2007<br /> * Time: 7:25:58 AM<br /> */<br /> public class EnumListConverter implements Converter<br /> {<br /> @SuppressWarnings({"unchecked"})<br /> public Object getAsObject(FacesContext context,<br /> UIComponent comp,<br /> String value)<br /> throws ConverterException<br /> {<br /> ValueBinding binding = comp.getValueBinding("value");<br /> Class enumType = binding.getType(context);<br /> if (enumType.isEnum()) // Single enum?<br /> return Enum.valueOf(enumType, value);<br /> else // List of enums.<br /> {<br /> // Find the s:selectItems so we can get the enum.<br /> List children = comp.getChildren();<br /> for (Object child : children)<br /> {<br /> if (child instanceof UIComponent)<br /> {<br /> UIComponent c = (UIComponent) child;<br /> ValueBinding b = c.getValueBinding("value");<br /> Class t = b.getType(context);<br /> // Array of enums: use the component type.<br /> if (t.isArray() && t.getComponentType().isEnum())<br /> {<br /> t = t.getComponentType();<br /> return Enum.valueOf(t,value);<br /> }<br /> else<br /> {<br /> Object v = b.getValue(context);<br /> // Collection of enum values, get the type of the first element.<br /> if (v instanceof Collection)<br /> {<br /> t = ((Collection) v).iterator().next().getClass();<br /> return Enum.valueOf(t,value);<br /> }<br /> }<br /> }<br /> }<br /> throw new ConverterException("Unable to find selectItems with enum values!");<br /> }<br /> }<br /> <br /> public String getAsString(FacesContext context,<br /> UIComponent component,<br /> Object object)<br /> throws ConverterException<br /> {<br /> if (object == null) {<br /> return null;<br /> }<br /> <br /> return ((Enum) object).name();<br /> }<br /> <br /> }<br /> </pre> <div> Retrieved from "<a </div> <img src ="http://www.aygfsteel.com/sealyu/aggbug/264599.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/sealyu/" target="_blank">seal</a> 2009-04-09 10:54 <a href="http://www.aygfsteel.com/sealyu/archive/2009/04/09/264599.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Richfaces?lt;a4j:repeat>标签判断最后一个元素的Ҏhttp://www.aygfsteel.com/sealyu/archive/2009/04/02/263588.htmlsealsealThu, 02 Apr 2009 09:42:00 GMThttp://www.aygfsteel.com/sealyu/archive/2009/04/02/263588.htmlhttp://www.aygfsteel.com/sealyu/comments/263588.htmlhttp://www.aygfsteel.com/sealyu/archive/2009/04/02/263588.html#Feedback0http://www.aygfsteel.com/sealyu/comments/commentRss/263588.htmlhttp://www.aygfsteel.com/sealyu/services/trackbacks/263588.html<a4j:repeat value="#{personList}" var="person" rowKeyVar="rowIndex">
<img src="img/arrow.png"> </img>
<h:outputText rendered="#{rowIndex == personList.size() -1}" value="#{entry.description}"/>
</a4j:repeat>

使用rowKeyVar按照上面的方法判断就可以?br />


seal 2009-04-02 17:42 发表评论
]]>
在JSF和SEAM中对java.util.Set及其子类作@?/title><link>http://www.aygfsteel.com/sealyu/archive/2009/04/01/263344.html</link><dc:creator>seal</dc:creator><author>seal</author><pubDate>Wed, 01 Apr 2009 05:47:00 GMT</pubDate><guid>http://www.aygfsteel.com/sealyu/archive/2009/04/01/263344.html</guid><wfw:comment>http://www.aygfsteel.com/sealyu/comments/263344.html</wfw:comment><comments>http://www.aygfsteel.com/sealyu/archive/2009/04/01/263344.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/sealyu/comments/commentRss/263344.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/sealyu/services/trackbacks/263344.html</trackback:ping><description><![CDATA[<h2>How to iterate over java.util.Set in JSF</h2> <small>By bozhobg</small> <p>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.<br /> - ui:repeat (facelets) doesn’t work<br /> - a4j:repeat (richfaces) doesn’t work<br /> - c:forEach works..only in case it does not rely on a variable defined by a parent component (rich:dataTable for instance)</p> <p>All above are pretty logical phenomena, as UIData relies on ordered data, and generally a Set is not ordered.</p> <p>In my case I had to use a Set defined in the Hibernate (JPA) object (PersistentSet).<br /> An important note: you should use a set in case the view order is of no matter to you.</p> <p>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</p> <p>reason for it not to be.</p> <p>1. Define your own UI component extending an existing repeater component. I used a4j:repeat (HtmlAjaxRepeat)<br /> 2. Override the metohd getDataModel<br /> 3. Define your component in your faces-config<br /> 4. create a custom facelets tag definition<br /> 5. Define a context-variable in web.xml pointing to the facelet tag definition.</p> <p>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.</p> <p>Now let’s see the steps in detail:</p> <p>1,2. Here some code:</p> <div> <div> <div><a onclick="dp.sh.Toolbar.Command('ViewSource',this);return false;">view plain</a><a onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;">copy to clipboard</a><a onclick="dp.sh.Toolbar.Command('PrintSource',this);return false;">print</a><a onclick="dp.sh.Toolbar.Command('About',this);return false;">?</a></div> </div> <ol> <li>package com.myproject.components;  </li> <li>import java.util.ArrayList;  </li> <li>import java.util.Set;  </li> <li>  </li> <li>import javax.faces.model.DataModel;  </li> <li>import javax.faces.model.ListDataModel;  </li> <li>  </li> <li>import org.ajax4jsf.component.html.HtmlAjaxRepeat;  </li> <li>import org.ajax4jsf.model.SequenceDataModel;  </li> <li>  </li> <li>public class UIIterator extends HtmlAjaxRepeat {  </li> <li>  </li> <li>   @SuppressWarnings("unchecked")  </li> <li>   @Override  </li> <li>   protected DataModel getDataModel() {  </li> <li>      Object current = getValue();  </li> <li>      if(current instanceof Set){  </li> <li>          return new SequenceDataModel(new ListDataModel(  </li> <li>                new ArrayList((Set) current)));  </li> <li>      }  </li> <li>      return super.getDataModel();  </li> <li>   }  </li> <li>}  </li> </ol> </div> <pre style="display: none;" name="code" class="java">package com.myproject.components; import java.util.ArrayList; import java.util.Set; import javax.faces.model.DataModel; import javax.faces.model.ListDataModel; import org.ajax4jsf.component.html.HtmlAjaxRepeat; import org.ajax4jsf.model.SequenceDataModel; public class UIIterator extends HtmlAjaxRepeat { @SuppressWarnings("unchecked") @Override protected DataModel getDataModel() { Object current = getValue(); if(current instanceof Set){ return new SequenceDataModel(new ListDataModel( new ArrayList((Set) current))); } return super.getDataModel(); } } </pre> <p>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.</p> <p>3. Add this to your faces-config. (I copied it from the a4j definition)</p> <div> <div> <div><a onclick="dp.sh.Toolbar.Command('ViewSource',this);return false;">view plain</a><a onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;">copy to clipboard</a><a onclick="dp.sh.Toolbar.Command('PrintSource',this);return false;">print</a><a onclick="dp.sh.Toolbar.Command('About',this);return false;">?</a></div> </div> <ol> <li><component>  </li> <li>        <description />  </li> <li>        <display-name>Iterator</display-name>  </li> <li>        <component-type>com.myproject.Iterator</component-type>  </li> <li>        <component-class>com.myproject.components.UIIterator</component-class>  </li> <li>  </li> <li>        <component-extension>  </li> <li>            <component-family>javax.faces.Data</component-family>  </li> <li>            <renderer-type>org.ajax4jsf.components.RepeatRenderera</renderer-type>  </li> <li>        </component-extension>  </li> <li>    </component>  </li> </ol> </div> <pre style="display: none;" name="code" class="xml"><component> <description /> <display-name>Iterator</display-name> <component-type>com.myproject.Iterator</component-type> <component-class>com.myproject.components.UIIterator</component-class> <component-extension> <component-family>javax.faces.Data</component-family> <renderer-type>org.ajax4jsf.components.RepeatRenderera</renderer-type> </component-extension> </component> </pre> <p>4. Here is the tag definition for facelets</p> <div> <div> <div><a onclick="dp.sh.Toolbar.Command('ViewSource',this);return false;">view plain</a><a onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;">copy to clipboard</a><a onclick="dp.sh.Toolbar.Command('PrintSource',this);return false;">print</a><a onclick="dp.sh.Toolbar.Command('About',this);return false;">?</a></div> </div> <ol> <li><?xml version="1.0" encoding="UTF-8"?>  </li> <li><!DOCTYPE facelet-taglib PUBLIC  </li> <li>"-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN"  </li> <li>"http://java.sun.com/dtd/facelet-taglib_1_0.dtd">  </li> <li><facelet-taglib xmlns="http://java.sun.com/JSF/Facelet">  </li> <li><namespace>http://myproject.com/cust</namespace>  </li> <li>  </li> <li><tag>  </li> <li><tag-name>repeat</tag-name>  </li> <li><component>  </li> <li><component-type>com.myproject.Iterator</component-type>  </li> <li><renderer-type>org.ajax4jsf.components.RepeatRenderer</renderer-type>  </li> <li></component>  </li> <li></tag>  </li> <li>  </li> <li></facelet-taglib>  </li> </ol> </div> <pre style="display: none;" name="code" class="xml"><?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE facelet-taglib PUBLIC "-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN" "http://java.sun.com/dtd/facelet-taglib_1_0.dtd"> <facelet-taglib xmlns="http://java.sun.com/JSF/Facelet"> <namespace>http://myproject.com/cust</namespace> <tag> <tag-name>repeat</tag-name> <component> <component-type>com.myproject.Iterator</component-type> <renderer-type>org.ajax4jsf.components.RepeatRenderer</renderer-type> </component> </tag> </facelet-taglib> </pre> <p>Save this file as /WEB-INF/facelets/custom.taglib.xml</p> <p>5. Add to your web.xml</p> <div> <div> <div><a onclick="dp.sh.Toolbar.Command('ViewSource',this);return false;">view plain</a><a onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;">copy to clipboard</a><a onclick="dp.sh.Toolbar.Command('PrintSource',this);return false;">print</a><a onclick="dp.sh.Toolbar.Command('About',this);return false;">?</a></div> </div> <ol> <li><context-param>  </li> <li><param-name>facelets.LIBRARIES</param-name>  </li> <li><param-value>/WEB-INF/facelets/custom.taglib.xml</param-value>  </li> <li></context-param>  </li> </ol> </div> <pre style="display: none;" name="code" class="xml"><context-param> <param-name>facelets.LIBRARIES</param-name> <param-value>/WEB-INF/facelets/custom.taglib.xml</param-value> </context-param> </pre> <p>6. It is now ready to use<br /> …<br /> xmlns:cust=”http://myproject.com/cust”<br /> …</p> <p><cust:repeat var=”myVar” value=”${aSet}”><br /> …<br /> </cust:repeat><br /> I think it is way neater than other workarounds, like defining a custom EL Resolver.</p> <hr /> <img src ="http://www.aygfsteel.com/sealyu/aggbug/263344.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/sealyu/" target="_blank">seal</a> 2009-04-01 13:47 <a href="http://www.aygfsteel.com/sealyu/archive/2009/04/01/263344.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <a href="http://www.aygfsteel.com/" title="狠狠久久亚洲欧美专区_中文字幕亚洲综合久久202_国产精品亚洲第五区在线_日本免费网站视频">狠狠久久亚洲欧美专区_中文字幕亚洲综合久久202_国产精品亚洲第五区在线_日本免费网站视频</a> </div> </footer> վ֩ģ壺 <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ƽ</a>| <a href="http://" target="_blank">ԭ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ͩ®</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">˳</a>| <a href="http://" target="_blank">̨</a>| <a href="http://" target="_blank">ڽ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">Ƽ</a>| <a href="http://" target="_blank">Դ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ʲ</a>| <a href="http://" target="_blank">ɽ</a>| <a href="http://" target="_blank">Ƹ</a>| <a href="http://" target="_blank">°Ͷ</a>| <a href="http://" target="_blank">°Ͷ</a>| <a href="http://" target="_blank">ֺ</a>| <a href="http://" target="_blank">ԭ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">Դ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ͤ</a>| <a href="http://" target="_blank">ʯ</a>| <a href="http://" target="_blank">ƺ</a>| <a href="http://" target="_blank">ɽ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ֶ</a>| <a href="http://" target="_blank">̨</a>| <a href="http://" target="_blank">ʯ</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>