锘??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲欧洲日本精品,亚洲VA中文字幕无码一二三区,中文字幕亚洲天堂http://m.tkk7.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://m.tkk7.com/sealyu/archive/2010/04/20/318792.htmlsealsealMon, 19 Apr 2010 16:36:00 GMThttp://m.tkk7.com/sealyu/archive/2010/04/20/318792.htmlhttp://m.tkk7.com/sealyu/comments/318792.htmlhttp://m.tkk7.com/sealyu/archive/2010/04/20/318792.html#Feedback0http://m.tkk7.com/sealyu/comments/commentRss/318792.htmlhttp://m.tkk7.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://m.tkk7.com/sealyu/archive/2009/12/07/304961.htmlsealsealMon, 07 Dec 2009 02:04:00 GMThttp://m.tkk7.com/sealyu/archive/2009/12/07/304961.htmlhttp://m.tkk7.com/sealyu/comments/304961.htmlhttp://m.tkk7.com/sealyu/archive/2009/12/07/304961.html#Feedback0http://m.tkk7.com/sealyu/comments/commentRss/304961.htmlhttp://m.tkk7.com/sealyu/services/trackbacks/304961.htmlCDATA 鍐呴儴鐨勬墍鏈変笢瑗塊兘浼氳瑙f瀽鍣ㄥ拷鐣ャ?/p>

鍋囧鏂囨湰涓寘鍚簡澶ч噺鐨?"<" 鍜?"&" 瀛楃 - 灝卞儚緙栫▼浠g爜涓粡甯稿嚭鐜扮殑鎯呭喌涓鏍?- 閭d箞榪欎釜 XML 鍏冪礌灝卞彲浠ヨ瀹氫箟涓轟竴涓?CDATA 閮ㄥ垎銆?/p>

CDATA 鍖烘寮濮嬩簬 "<![CDATA["錛岀粨鏉熶簬 "]]>"錛?/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 鍖烘涓殑鎵鏈変笢瑗塊兘浼氳瑙f瀽鍣ㄥ拷鐣ャ?/p>


鍏充簬 CDATA 鍖烘鐨勬敞閲?

CDATA 鍖烘涓嶈兘鍖呭惈瀛楃涓?"]]>"錛屾墍浠ワ紝CDATA 鍖烘鐨勫祵濂楁槸涓嶈鍏佽鐨勩?/p>

鍚屾椂涔熼渶瑕佺‘淇濆湪 "]]>" 瀛楃涓蹭腑娌℃湁絀烘牸鎴栨姌琛屻?/p>

涓轟粈涔堣浣跨敤CDATA:

       XHTML鐨勭浜屼釜鏀瑰彉鏄嬌鐢–DATA孌點俋ML涓殑CDATA孌電敤浜庡0鏄庝笉搴旇瑙f瀽涓烘爣絳劇殑鏂囨湰錛圶HTML涔熸槸濡傛錛夛紝榪欐牱灝卞彲浠ヤ嬌鐢ㄧ壒孌婂瓧絎︼紝濡? 灝忎簬錛?lt;錛夈佸ぇ浜庯紙>錛夈佸拰鍙鳳紙&錛夊拰鍙屽紩鍙鳳紙"錛夛紝鑰屼笉蹇呬嬌鐢ㄥ畠浠殑瀛楃瀹炰綋銆傝冭檻涓嬮潰鐨勪唬鐮侊細

<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>

榪欎釜鍑芥暟鐩稿綋綆鍗曪紝瀹冩瘮杈冩暟瀛梐鍜宐錛岀劧鍚庢樉紺烘秷鎭鏄庡畠浠殑鍏崇郴銆備絾鏄紝鍦╔HTML涓紝榪欐浠g爜鏄棤鏁堢殑錛屽洜涓哄畠浣跨敤浜嗕笁涓壒孌婄鍙鳳紝鍗沖皬浜庛? 澶т簬鍜屽弻寮曞彿銆傝淇榪欎釜闂錛屽繀欏誨垎鍒敤榪欎笁涓瓧絎︾殑XML瀹炰綋&lt;銆?amp;gt;鍜?amp;quot;鏇挎崲瀹冧滑錛?/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>

榪欐浠g爜瀛樺湪涓や釜闂銆傞鍏堬紝寮鍙戣呬笉涔犳儻鐢╔ML瀹炰綋緙栧啓浠g爜銆傝繖浣夸唬鐮佸緢闅捐鎳傘傚叾嬈★紝鍦↗avaScript涓紝榪欑浠g爜瀹為檯涓婂皢瑙嗕負鏈夎娉? 閿欙紝鍥犱負瑙i噴紼嬪簭涓嶇煡閬揦ML瀹炰綋鐨勬剰鎬濄傜敤CDATA孌靛嵆鍙互浠ュ父瑙勫艦寮忥紙鍗蟲槗璇葷殑璇硶錛夌紪鍐橨avaScript浠g爜銆傛寮忓姞鍏DATA孌電殑鏂規硶濡? 涓嬶細

<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>

铏界劧榪欐槸姝e紡鏂瑰紡錛屼絾榪樿璁頒綇錛屽ぇ澶氭暟嫻忚鍣ㄩ兘涓嶅畬鍏ㄦ敮鎸乆HTML錛岃繖灝卞甫鏉ヤ富瑕侀棶棰橈紝鍗寵繖鍦↗avaScript涓槸涓娉曢敊璇紝鍥犱負澶у鏁版祻瑙堝櫒榪樹笉璁よ瘑CDATA孌點?/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>

褰撳墠浣跨敤鐨勮В鍐蟲柟妗堟ā浠夸簡“瀵規棫嫻忚鍣ㄩ殣钘?#8221;浠g爜鐨勬柟娉曘備嬌鐢ㄥ崟琛岀殑JavaScript娉ㄩ噴"http://"錛屽彲鍦ㄤ笉褰卞搷浠g爜璇硶鐨勬儏鍐典笅宓屽叆CDATA孌碉細

鐜板湪錛岃繖孌典唬鐮佸湪涓嶆敮鎸乆HTML鐨勬祻瑙堝櫒涓篃鍙繍琛屻?/p>

浣嗘槸錛屼負閬垮厤CDATA鐨勯棶棰橈紝鏈濂借繕鏄敤澶栭儴鏂囦歡寮曞叆JavaScript浠g爜銆?/p>

seal 2009-12-07 10:04 鍙戣〃璇勮
]]>
richfaces 鐨勮剼鏈啿紿侀棶棰橈紙prototype.js錛?/title><link>http://m.tkk7.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://m.tkk7.com/sealyu/archive/2009/10/28/300003.html</guid><wfw:comment>http://m.tkk7.com/sealyu/comments/300003.html</wfw:comment><comments>http://m.tkk7.com/sealyu/archive/2009/10/28/300003.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/sealyu/comments/commentRss/300003.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/sealyu/services/trackbacks/300003.html</trackback:ping><description><![CDATA[鍦ㄩ〉闈腑浣跨敤浜唕ichfaces鍜宲rototype錛岀粨鏋滃湪IE涓嬩竴鐩存姤閿欙紝鍚庢潵鍙戠幇richfaces鐨勬枃妗d腑宸茬粡鏍囨敞浜嗘闂錛?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://m.tkk7.com/sealyu/aggbug/300003.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/sealyu/" target="_blank">seal</a> 2009-10-28 08:11 <a href="http://m.tkk7.com/sealyu/archive/2009/10/28/300003.html#Feedback" target="_blank" style="text-decoration:none;">鍙戣〃璇勮</a></div>]]></description></item><item><title>Seam鎵╁睍浜嬪姟娑堟伅http://m.tkk7.com/sealyu/archive/2009/10/23/299454.htmlsealsealFri, 23 Oct 2009 02:40:00 GMThttp://m.tkk7.com/sealyu/archive/2009/10/23/299454.htmlhttp://m.tkk7.com/sealyu/comments/299454.htmlhttp://m.tkk7.com/sealyu/archive/2009/10/23/299454.html#Feedback0http://m.tkk7.com/sealyu/comments/commentRss/299454.htmlhttp://m.tkk7.com/sealyu/services/trackbacks/299454.html 褰撲簨鍔℃垚鍔熶箣鍚庯紙璋冪敤 persist()銆?tt>update() 鎴?remove() 鎴愬姛鍚庯級錛孒ome瀵硅薄浼氬彂鍑轟竴涓?org.jboss.seam.afterTransactionSuccess 浜嬩歡銆? 閫氳繃鐩戝惉榪欎竴浜嬩歡錛屾垜浠彲浠ュ湪搴曞眰瀹炰綋鏀瑰彉鍚庯紝鍒鋒柊鏌ヨ銆? 濡傛灉鎴戜滑鍙渶瑕佸湪鐗瑰畾鐨勫疄浣撲繚瀛樸佷慨鏀規垨鍒犻櫎鍚庡埛鏂扮壒瀹氭煡璇紝鎴戜滑鍙互鐩戣 org.jboss.seam.afterTransactionSuccess.<name> 浜嬩歡錛?tt><name> 鏄疄浣撶殑鍚嶅瓧錛夈?

褰撲竴涓搷浣滄垚鍔熸椂錛孒ome瀵硅薄鍙互鑷姩鍦版樉紺篎aces淇℃伅錛屾垜浠彲浠ュ啀涓嬈¢氳繃閰嶇疆鏉ュ畾鍒朵俊鎭?

<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涓紙鍦ㄩ粯璁ゆ儏鍐典笅錛岃繖涓猙undle鍙仛 messages 錛夈?

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

榪欐牱鏂逛究榪涜鍥介檯鍖栵紝浠庤〃鐜板眰鐨勮搴﹁冭檻涔熶繚鎸佷簡浠g爜鍜岄厤緗殑鏁存磥銆?

鏈鍚庝竴姝ユ槸浣跨敤 <s:validateAll> 鍜?<s:decorate> 鍚戦〉闈腑娣誨姞楠岃瘉鍔熻兘錛屾垜浼氭妸榪欎釜鐣欑粰浣犱滑鑷繁鍘誨疄鐜般?



seal 2009-10-23 10:40 鍙戣〃璇勮
]]>
瑙e喅Safari涓璕ichfaces鏌愪簺緇勪歡涓嶅吋瀹圭殑闂http://m.tkk7.com/sealyu/archive/2009/09/22/295950.htmlsealsealTue, 22 Sep 2009 01:56:00 GMThttp://m.tkk7.com/sealyu/archive/2009/09/22/295950.htmlhttp://m.tkk7.com/sealyu/comments/295950.htmlhttp://m.tkk7.com/sealyu/archive/2009/09/22/295950.html#Feedback0http://m.tkk7.com/sealyu/comments/commentRss/295950.htmlhttp://m.tkk7.com/sealyu/services/trackbacks/295950.html 鎰熻鏃犱粠鏌ヨ搗錛屽彧鑳藉熷姪Google銆?br /> 鎵嶅彂鐜板師鏉afari涓嬪緢澶歊ichfaces鐨勭粍浠墮兘浼氬嚭鐜伴棶棰橈紝瑙e喅鏂規硶鍙嶈屽緢綆鍗曪細
鍦ㄤ綘鐨剎html欏甸潰錛堟垨鑰呬綘鐢╦sp鎴栧叾浠栨ā鏉挎妧鏈級鐨勯〉棣栦綅緗紝鍔犺繖琛岋細
<f:view contentType="text/html" />

闂瑙e喅銆?/pre>



seal 2009-09-22 09:56 鍙戣〃璇勮
]]>Seam涓畝鍗曠殑checkbox鎿嶄綔http://m.tkk7.com/sealyu/archive/2009/09/02/293563.htmlsealsealWed, 02 Sep 2009 03:26:00 GMThttp://m.tkk7.com/sealyu/archive/2009/09/02/293563.htmlhttp://m.tkk7.com/sealyu/comments/293563.htmlhttp://m.tkk7.com/sealyu/archive/2009/09/02/293563.html#Feedback0http://m.tkk7.com/sealyu/comments/commentRss/293563.htmlhttp://m.tkk7.com/sealyu/services/trackbacks/293563.html 鍦ㄤ嬌鐢⊿eam鍜孯ichfaces寮鍙戠殑鏃跺欙紝涓涓畝鍗曠殑a4j:support 鍜?reRender 騫朵笉鑳借В鍐抽棶棰樸傝瘯楠屼簡涓鐣紝瑙e喅浜嗚繖涓棶棰橈紝渚嬪瓙浠g爜錛?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鐨刾rocess灞炴ф潵鎺у埗灝卞彲浠ヨВ鍐抽棶棰樸?br />

seal 2009-09-02 11:26 鍙戣〃璇勮
]]>
Seam涓湪java鏂囦歡涓嬌鐢ㄨ祫婧愭枃浠?/title><link>http://m.tkk7.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://m.tkk7.com/sealyu/archive/2009/09/01/293425.html</guid><wfw:comment>http://m.tkk7.com/sealyu/comments/293425.html</wfw:comment><comments>http://m.tkk7.com/sealyu/archive/2009/09/01/293425.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/sealyu/comments/commentRss/293425.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/sealyu/services/trackbacks/293425.html</trackback:ping><description><![CDATA[鍦╦ava 涓鏋滄兂浠庡浗闄呭寲璧勬簮鏂囦歡涓鍙栨枃鏈紝鍙互閫氳繃娉ㄥ叆seam鐨勪竴涓粍浠訛細<br /> @In(value="org.jboss.seam.international.messages")<br />     private Map<String, String> messages;<br /> <br /> 鍦ㄤ嬌鐢ㄦ椂錛屽彧闇瑕佸儚涓嬮潰榪欐牱錛?br /> String abc = messages.get("person.name.required");<br /> <img src ="http://m.tkk7.com/sealyu/aggbug/293425.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/sealyu/" target="_blank">seal</a> 2009-09-01 11:41 <a href="http://m.tkk7.com/sealyu/archive/2009/09/01/293425.html#Feedback" target="_blank" style="text-decoration:none;">鍙戣〃璇勮</a></div>]]></description></item><item><title>Seam 欏圭洰閮ㄧ講鍦?tomcat 涓?杞?http://m.tkk7.com/sealyu/archive/2009/08/26/292632.htmlsealsealWed, 26 Aug 2009 04:36:00 GMThttp://m.tkk7.com/sealyu/archive/2009/08/26/292632.htmlhttp://m.tkk7.com/sealyu/comments/292632.htmlhttp://m.tkk7.com/sealyu/archive/2009/08/26/292632.html#Feedback0http://m.tkk7.com/sealyu/comments/commentRss/292632.htmlhttp://m.tkk7.com/sealyu/services/trackbacks/292632.html JBoss Tools 鐢熸垚鐨?nbsp;Seam 欏圭洰錛堟柊寤洪」鐩椂錛屾湇鍔″櫒閫夋嫨 tomcat錛夛紝浼氱敓鎴愪竴浜涘繀瑕佺殑鏂囦歡錛屽錛氳繛鎺ユ暟鎹簱鐨勬暟鎹簮鏂囦歡錛屽錛?/font>project-ds.xml 錛堜絾瀹冨彧鑳藉湪 Jboss as 鐨勭幆澧冧腑榪愯錛屼笉閫傜敤浜?nbsp;tomcat錛夛紝瑕佹兂寰堟垜浠殑欏圭洰錛?/font>war錛夎繍琛屼簬 tomcat 涓殑錛屾垜浠緱瀵瑰畠鑷姩鐢熸垚鐨勬枃浠跺仛涓浜涘繀瑕佺殑淇敼銆?/font>

      涓銆?span style="font-weight: normal; font-size: 10.5pt; font-family: '瀹嬩綋';">淇敼鏁版嵁搴撶殑榪炴帴鏂瑰紡

         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 鐨勮繛鎺ユ暟鎹簱鐨勬柟寮忥紝濡備笅錛?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 閰嶇疆鏂囦歡 persistence.xml

          1銆?/span>濡傛灉鏁版嵁鐨勮繛鎺ユ柟寮忛噰鐢ㄦ暟鎹簮鐨勫艦寮忥紝鍒欏彧闇淇敼閲岄潰鏁版嵁婧愮殑鍚嶇О錛屽錛?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 錛?nbsp;

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

      涓夈?span style="font-weight: normal; font-size: 10.5pt; font-family: '瀹嬩綋';">閰嶇疆 Seam 鐨勪簨鍔$鐞嗗櫒
          鍦?nbsp;component.xml 鏂囦歡鍔犲叆錛?br />           <transaction:entity-transaction entity-manager="#{entityManager}"/>
         榛樿鐢熸垚鐨勬鏂囦歡鏄笉鍚湁 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涓璬rag鍜宒rop鍚巖eRender瀵瑰簲鐨則reehttp://m.tkk7.com/sealyu/archive/2009/08/13/291006.htmlsealsealThu, 13 Aug 2009 07:05:00 GMThttp://m.tkk7.com/sealyu/archive/2009/08/13/291006.htmlhttp://m.tkk7.com/sealyu/comments/291006.htmlhttp://m.tkk7.com/sealyu/archive/2009/08/13/291006.html#Feedback0http://m.tkk7.com/sealyu/comments/commentRss/291006.htmlhttp://m.tkk7.com/sealyu/services/trackbacks/291006.html 鍦―ropEvent瀵瑰簲鐨刲istener鐨勬柟娉曚腑鍙互璋冪敤AjaxContext閲嶆柊reRender錛?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());

鍙﹀錛屽鏋滆鍦ㄦ嫋鎷藉悗reRender鍏朵粬鐨勮妭鐐癸紝瑕佺敤鍒皁ncomplete灞炴э紝浣跨敤涓涓猨sfunction鏉eRender銆傚崟綰殑reRender涓嶈搗浣滅敤錛屾垜鐚滃師鍥犲彲鑳芥槸listener騫朵笉鏄寜鐓т竴涓猘jax璇鋒眰鐨勬柟寮忔潵鐨勶紝鎵浠ュ崟綰殑ajax reRender涔熶笉璧蜂綔鐢ㄣ?br />



seal 2009-08-13 15:05 鍙戣〃璇勮
]]>
SEAM鐨凱AGE鍜孋ONVERSATION contexthttp://m.tkk7.com/sealyu/archive/2009/08/13/291001.htmlsealsealThu, 13 Aug 2009 06:53:00 GMThttp://m.tkk7.com/sealyu/archive/2009/08/13/291001.htmlhttp://m.tkk7.com/sealyu/comments/291001.htmlhttp://m.tkk7.com/sealyu/archive/2009/08/13/291001.html#Feedback0http://m.tkk7.com/sealyu/comments/commentRss/291001.htmlhttp://m.tkk7.com/sealyu/services/trackbacks/291001.html 濡傛灉鍦ㄤ竴涓〉闈腑淇濇寔鐘舵? 浼樺厛浣跨敤PAGE context,榪欐牱鍙互鎻愰珮鏁堢巼.



seal 2009-08-13 14:53 鍙戣〃璇勮
]]>
rich:tree 鐨?adviseNodeOpened 鍜?adviseNodeSelected灞炴?/title><link>http://m.tkk7.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://m.tkk7.com/sealyu/archive/2009/08/13/291000.html</guid><wfw:comment>http://m.tkk7.com/sealyu/comments/291000.html</wfw:comment><comments>http://m.tkk7.com/sealyu/archive/2009/08/13/291000.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/sealyu/comments/commentRss/291000.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/sealyu/services/trackbacks/291000.html</trackback:ping><description><![CDATA[鍦╮ich:tree涓鏋滄兂瑕佸湪欏甸潰涓垵濮嬪寲tree鐨勫睍寮鍜岄変腑鐘舵佹垨鑰呭湪欏甸潰鏇存敼鍚庤繑鍥炴椂淇濇寔涔嬪墠鐨勭姸鎬侊紝<br /> 鍙互璁劇疆tree鐨刟dviseNodeOpened 鍜?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://m.tkk7.com/sealyu/aggbug/291000.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/sealyu/" target="_blank">seal</a> 2009-08-13 14:51 <a href="http://m.tkk7.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://m.tkk7.com/sealyu/archive/2009/07/20/287417.htmlsealsealMon, 20 Jul 2009 02:17:00 GMThttp://m.tkk7.com/sealyu/archive/2009/07/20/287417.htmlhttp://m.tkk7.com/sealyu/comments/287417.htmlhttp://m.tkk7.com/sealyu/archive/2009/07/20/287417.html#Feedback0http://m.tkk7.com/sealyu/comments/commentRss/287417.htmlhttp://m.tkk7.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閿欒錛?Property 鈥榵xx鈥?not readable on type java.lang.Boolean http://m.tkk7.com/sealyu/archive/2009/07/20/287397.htmlsealsealMon, 20 Jul 2009 01:24:00 GMThttp://m.tkk7.com/sealyu/archive/2009/07/20/287397.htmlhttp://m.tkk7.com/sealyu/comments/287397.htmlhttp://m.tkk7.com/sealyu/archive/2009/07/20/287397.html#Feedback0http://m.tkk7.com/sealyu/comments/commentRss/287397.htmlhttp://m.tkk7.com/sealyu/services/trackbacks/287397.html 閿欒濡備笅錛?br /> 鍦ㄤ嬌鐢╮ich:inplaceSelect鍋氫竴涓竷灝斿瀷鐨勯夋嫨妗嗘椂錛岀敱浜庡鎴烽渶瑕侊紝鍦ㄧ壒瀹氭儏鍐典笅闇瑕佷竴涓粯璁ゅ鹼紝涔熷氨鏄痳ich:inplaceSelect鐨刣efaultLabel錛岃繖鏃跺氨闇瑕侀櫎浜唗rue鍜宖alse澶栧啀鏈変竴涓猲ull鐨勫鹼紝鎵浠ラ渶瑕佸皢鍚庡彴session bean涓殑瀵瑰簲灞炴х敱鍘熷綾誨瀷boolean鏀逛負Boolean錛屽湪鏀瑰畬涔嬪悗錛岄噸鏂拌繍琛岀▼搴忔姤閿欙細
Property ‘xxx’ not readable on type java.lang.Boolean
鍒嗘瀽浜嗕竴涓嬶紝鎵句笉鍑轟粈涔堝彲鑳界殑鍘熷洜錛屾渶鍚庡湪涓鐗囧笘瀛愪腑鍙戠幇浜嗗搴旂殑淇℃伅錛?br /> 鍘熸潵JSF灝嗗師濮嬬被鍨媌oolean鐨刧et鏂規硶榛樿涓篿s....(),鑰屽皢灝佽綾誨瀷Boolean鐨刧et鏂規硶榛樿涓篻et...().

Ok,鍦ㄥ悗鍙板皢瀵瑰簲閭d釜鐨勬柟娉曚慨鏀癸紝闂瑙e喅銆?br />

seal 2009-07-20 09:24 鍙戣〃璇勮
]]>
Seam閿欒錛歰rg.jboss.seam.InstantiationException: Could not instantiate Seam componenthttp://m.tkk7.com/sealyu/archive/2009/07/17/287082.htmlsealsealFri, 17 Jul 2009 01:53:00 GMThttp://m.tkk7.com/sealyu/archive/2009/07/17/287082.htmlhttp://m.tkk7.com/sealyu/comments/287082.htmlhttp://m.tkk7.com/sealyu/archive/2009/07/17/287082.html#Feedback0http://m.tkk7.com/sealyu/comments/commentRss/287082.htmlhttp://m.tkk7.com/sealyu/services/trackbacks/287082.html org.jboss.seam.InstantiationException: Could not instantiate Seam component: xxxAction
鎵句簡濂戒箙錛岀粓浜庡彂鐜頒簡閿欒鍘熷洜錛?br /> 鍘熸潵鏄搴旂殑@Stateful鐨剆ession bean瀵瑰簲鐨勬帴鍙f病鏈夋爣娉細@Local
The devil's in the Details錛佹灉鐒跺姝ゅ晩


seal 2009-07-17 09:53 鍙戣〃璇勮
]]>
鍦╮ich:inplaceSelect 涓嬌鐢ㄥ竷灝斿瀷鐨剆electItem鏃剁鍒扮殑闂http://m.tkk7.com/sealyu/archive/2009/07/10/286288.htmlsealsealFri, 10 Jul 2009 09:13:00 GMThttp://m.tkk7.com/sealyu/archive/2009/07/10/286288.htmlhttp://m.tkk7.com/sealyu/comments/286288.htmlhttp://m.tkk7.com/sealyu/archive/2009/07/10/286288.html#Feedback0http://m.tkk7.com/sealyu/comments/commentRss/286288.htmlhttp://m.tkk7.com/sealyu/services/trackbacks/286288.html
鎴戜滑閮界煡閬擄紝鍦?lt;h:selectOneMenu>涓嬌鐢ㄥ竷灝斿瀷selectItem鏃訛紝itemValue涓?true"/"false".渚嬪錛?br /> <h:selectOneMenu  value="#{controller.booleanPropertyX}">
    <f:selectItem itemLabel="#{messages['xxxxx']}" itemValue="true"/>
    <f:selectItem itemLabel="#{messages['xxxxx']}" itemValue="false"/>
</
h:selectOneMenu>
榪欐牱鏄病鏈夐棶棰樼殑銆?br /> 浣嗘槸濡傛灉浣犱嬌鐢?lt;rich:inplaceSelect>鏉ュ疄鐜伴夋嫨鍔熻兘鐨勬椂鍊欙紝"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>

榪欐椂鍊欏嵆浣縮fsb涓殑鍊?font size="2">booleanPropertyX鏄?true"/"false"錛屼篃涓嶄細鏈塻electItem琚変腑錛岃屼笖濡傛灉浣犻夋嫨涓涓猻electItem錛岃繕浼氭姤閿?IllegalArgumentException.璇存槑selectItem鐨刬temValue璺?/font>#{controller.booleanPropertyX}鐨勫兼槸涓嶅尮閰嶇殑銆?br /> 鍚庢潵鎴戝皢"true"/"false"鏀逛負"0"/"1", 榪樻槸涓嶈搗浣滅敤銆?br />
Finally錛岀粓浜庤瘯鍑轟簡姝g‘鐨勬柟娉曪細浣跨敤"#{true}"/"#{false}". 姝g‘鐨勪嬌鐢ㄦ柟娉曪細
<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>


涔熷氨鏄錛?br /> 錛?錛夈傚鏋滀綘浣跨敤<h:selectOneMenu>錛岄偅涔堜綘鐨刦:selectItem鐨刬temValue搴旇浣跨敤錛?true"/"false"
錛?錛夈傚鏋滀綘浣跨敤<rich:inplaceSelect>錛岄偅涔堜綘鐨?/font>f:selectItem鐨刬temValue搴旇浣跨敤錛?#{true}"/"#{false}"

鍘熷洜鏆傛椂榪樻病鐮旂┒鍑烘潵錛屼絾鏄粨鏋滃氨鏄繖鏍風殑浜嗐?br />

seal 2009-07-10 17:13 鍙戣〃璇勮
]]>
JBoss涓殑TransactionTimeOut鐨勮緗?/title><link>http://m.tkk7.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://m.tkk7.com/sealyu/archive/2009/05/18/271239.html</guid><wfw:comment>http://m.tkk7.com/sealyu/comments/271239.html</wfw:comment><comments>http://m.tkk7.com/sealyu/archive/2009/05/18/271239.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/sealyu/comments/commentRss/271239.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/sealyu/services/trackbacks/271239.html</trackback:ping><description><![CDATA[榪欎袱澶╁湪浣渟eam鐨勬椂鍊欎笉鏃墮亣鍒?#8220;org.jboss.util.NestedSQLException: Transaction is not active”鐨勯敊璇俊鎭紝鍚庢潵鍒癹boss鐨剋iki涓婂彂鐜頒簡闂鐨勫師鍥犲拰瑙e喅鏂規硶錛?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://m.tkk7.com/sealyu/aggbug/271239.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/sealyu/" target="_blank">seal</a> 2009-05-18 10:01 <a href="http://m.tkk7.com/sealyu/archive/2009/05/18/271239.html#Feedback" target="_blank" style="text-decoration:none;">鍙戣〃璇勮</a></div>]]></description></item><item><title>Seam 璁頒綇鐧誨綍鍓島rl鐨勬柟娉?/title><link>http://m.tkk7.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://m.tkk7.com/sealyu/archive/2009/05/13/270343.html</guid><wfw:comment>http://m.tkk7.com/sealyu/comments/270343.html</wfw:comment><comments>http://m.tkk7.com/sealyu/archive/2009/05/13/270343.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/sealyu/comments/commentRss/270343.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/sealyu/services/trackbacks/270343.html</trackback:ping><description><![CDATA[<p>seam鏈変釜涓涓唴緗殑component錛屽彨鍋歳edirect銆傚畠鍏鋒湁鑾峰彇褰撳墠view鐨勮兘鍔涘綋寰楀埌鐧婚檰鎺堟潈鍚庯紝鍙互鐩存帴鑾峰緱鐧誨綍鍓嶇殑鍦板潃榪涜璁塊棶銆?/p> <p>鍦╟omponent.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://m.tkk7.com/sealyu/aggbug/270343.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/sealyu/" target="_blank">seal</a> 2009-05-13 09:36 <a href="http://m.tkk7.com/sealyu/archive/2009/05/13/270343.html#Feedback" target="_blank" style="text-decoration:none;">鍙戣〃璇勮</a></div>]]></description></item><item><title>Seam閿欒錛歞eleted entity passed to persisthttp://m.tkk7.com/sealyu/archive/2009/05/08/269520.htmlsealsealFri, 08 May 2009 00:59:00 GMThttp://m.tkk7.com/sealyu/archive/2009/05/08/269520.htmlhttp://m.tkk7.com/sealyu/comments/269520.htmlhttp://m.tkk7.com/sealyu/archive/2009/05/08/269520.html#Feedback0http://m.tkk7.com/sealyu/comments/commentRss/269520.htmlhttp://m.tkk7.com/sealyu/services/trackbacks/269520.html 鍗曠函鐪嬮敊璇俊鎭紝榪樹互涓烘槸瀵硅薄娌℃湁浼犺繘鍘匯備絾璋冭瘯涔嬪悗鍙戠幇personHome閲岄潰鐨勫璞℃槸姝g‘鐨勩?br /> 鍚庢潵嫻嬭瘯浜嗗嚑嬈″彂鐜版槸鍥犱負鎵瑕佸垹闄ょ殑瀵硅薄闅跺睘浜庡彟澶栦竴涓璞★紝閭d箞鍗曠函鍒犻櫎姝ゅ璞℃椂錛屼細鎶ヨ繖涓敊璇紝鍥犱負姝ゆ椂鐨勭害鏉熷叧緋昏繕鏈В闄ゃ?br /> 渚嬪錛?br /> 鎴戣鍒犻櫎涓涓狿erson瀹炰綋錛岃岃繖涓疄浣撴槸灞炰簬涓涓粍緇嘍epartment鐨勶紝
閭d箞鎴戝簲璇ュ湪鍒犻櫎涔嬪墠鍏堟墽琛岋細 personHome.getInstance().getDepartment.getAllPersons().remove(personHome.getInstance()),
鐒跺悗鍐嶆墽琛宲ersonHome.remove().


seal 2009-05-08 08:59 鍙戣〃璇勮
]]>
鎻愰珮JSF錛廠EAM紼嬪簭鐨勬晥鐜囷紙杞級http://m.tkk7.com/sealyu/archive/2009/05/07/269329.htmlsealsealThu, 07 May 2009 01:16:00 GMThttp://m.tkk7.com/sealyu/archive/2009/05/07/269329.htmlhttp://m.tkk7.com/sealyu/comments/269329.htmlhttp://m.tkk7.com/sealyu/archive/2009/05/07/269329.html#Feedback0http://m.tkk7.com/sealyu/comments/commentRss/269329.htmlhttp://m.tkk7.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://m.tkk7.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://m.tkk7.com/sealyu/archive/2009/05/06/269248.html</guid><wfw:comment>http://m.tkk7.com/sealyu/comments/269248.html</wfw:comment><comments>http://m.tkk7.com/sealyu/archive/2009/05/06/269248.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/sealyu/comments/commentRss/269248.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/sealyu/services/trackbacks/269248.html</trackback:ping><description><![CDATA[<br /> 浣滆咃細 sealyu   鏃ユ湡錛?009-05-06<br /> <br /> 鍦⊿eam涓紝濡傛灉瑕佹彁渚涗竴涓泦鍚堝睘鎬т紶鍒伴〉闈紝閭d箞鍙互鏈変袱縐嶉夋嫨錛?br /> 錛?).鍦⊿FSB涓緩涓涓泦鍚堝睘鎬э紝騫跺緩绔嬩竴涓柟娉曠敤鏉ュ彇寰楀搴旂殑鏁版嵁銆備緥濡傛垜浠湁涓涓猄FSB錛圱estAction.java錛夛細<br /> 錛燬tateful  <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 /> 浣嗘槸榪欑鏂規硶鏈夌緙虹偣錛屽洜涓哄皢瀵瑰簲鐨勫艱祴鍊肩粰涓涓狫SF緇勪歡錛屾墍浠ュ湪鍒鋒柊涓涓〉闈㈢殑鏃跺欑粡甯擱渶瑕佽皟鐢ㄥ緢澶氭鍙栨暟鎹殑鍑芥暟錛屽嵆浣夸綘浣滃垽鏂紙渚嬪錛氬綋鍊間笉涓虹┖鐨勬椂鍊欎笉鍐嶉噸鏂板彇鍊鹼級錛岃繖涓嚱鏁拌繕鏄細鎵ц寰堝嬈★紝鍙兘浼氶犳垚鏁堢巼鐨勯棶棰樸?br /> 浣嗘槸榪欑鏂規硶鐨勫ソ澶勬槸鎬繪槸鍙互鍙栧緱鏈鏂扮殑鏁版嵁銆傚湪浣犵粡甯擱氳繃浼犻掑弬鏁版潵鍙栧緱鏁版嵁鍒楄〃鐨勬椂鍊欙紝榪欑鏂規硶姣旇緝濂姐?br /> 錛?).浣跨敤錛燜actory. <br /> 錛燜actory鏈変袱縐嶏紝鍦ㄥ畠鐨刯avadoc閲岄潰鏄繖涔堣鐨勶細<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>絎竴縐嶅伐鍘傛柟娉?</strong><br /> 榪欑宸ュ巶鏂規硶娌℃湁榪斿洖鍊鹼紝浣嗘槸浣犻渶瑕佸皢寰楀埌鐨勬暟鎹敞鍑哄埌context閲岄潰錛屽ぇ澶氭暟鎯呭喌涓嬩綘鍙互鐩存帴浣跨敤錛燚ataModel錛屼緥濡傦細<br /> 錛燬tateful  <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>絎簩縐嶅伐鍘傛柟娉曪細</strong><br /> 榪欑宸ュ巶鏂規硶鏈夎繑鍥炲鹼紝seam浼氭牴鎹畇cope鐨勫煎皢鏁版嵁緇戝畾鍒板搴旂殑涓婁笅鏂囦腑銆備嬌鐢ㄨ繖縐嶆柟娉曪紝浣犱笉鐢ㄦ樉寮忕殑娉ㄥ嚭銆備緥濡傦細<br /> <br /> 錛燬tateful  <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 /> 涓嶇浣跨敤鍝鏂規硶錛屼綘閮藉彲浠ュ湪欏甸潰涓洿鎺ヨ闂繖涓猣actory鐨勫鹼細<br /> <rich:dataTable value="#{personList}" id="xxx"/><br /> <br /> 浣跨敤錛燜actory鐨勫ソ澶勬槸涓嶇敤閲嶅鐨勫幓鍙栧鹼紝浣嗘槸鍚屾椂涔熸湁涓涓己鐐癸細<br />   浣跨敤@Factory鐨勬椂鍊欙紝鍙湁鍦╟ontext涓病鏈夎繖涓狜Factory鎵瀵瑰簲鐨勭粦瀹氬肩殑鏃跺欙紝seam鎵嶄細閲嶆柊鎵ц宸ュ巶鏂規硶鏉ュ彇寰楄繖涓箋傛墍浠ュ鏋滀綘鎯寵鍦–RUD涓涓疄浣撲箣鍚庢洿鏂板垪琛ㄧ殑璇濓紝浣犲彲浠ョ洃鍚琽rg.jboss.seam.afterTransactionSuccess.XXEntity浜嬩歡鏉ユ洿鏂拌繖涓紶Factory鐨勫箋傛殏鏃舵病鎵懼埌寮哄埗娓呯┖騫跺埛鏂幫紶Factory鐨勬柟娉曪紝seam濂藉儚鐜板湪騫舵病鏈夋彁渚涜繖涓柟娉曪紝鎵浠ユ垜鐜板湪鏄洿鎺ユ竻絀猴紶Factory鎵瀵瑰簲鐨刲ist鐨勫兼潵杈懼埌鍒鋒柊鐨勭洰鐨勩?br /> <br /> <br /> <img src ="http://m.tkk7.com/sealyu/aggbug/269248.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/sealyu/" target="_blank">seal</a> 2009-05-06 15:30 <a href="http://m.tkk7.com/sealyu/archive/2009/05/06/269248.html#Feedback" target="_blank" style="text-decoration:none;">鍙戣〃璇勮</a></div>]]></description></item><item><title>鍦▁html涓嬌鐢ㄧ┖鏍?/title><link>http://m.tkk7.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://m.tkk7.com/sealyu/archive/2009/04/29/268052.html</guid><wfw:comment>http://m.tkk7.com/sealyu/comments/268052.html</wfw:comment><comments>http://m.tkk7.com/sealyu/archive/2009/04/29/268052.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://m.tkk7.com/sealyu/comments/commentRss/268052.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/sealyu/services/trackbacks/268052.html</trackback:ping><description><![CDATA[鍦▁html欏甸潰涓姞鍏ョ┖鏍間笉鑳戒嬌鐢?&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://m.tkk7.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://m.tkk7.com/sealyu/aggbug/268052.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/sealyu/" target="_blank">seal</a> 2009-04-29 10:21 <a href="http://m.tkk7.com/sealyu/archive/2009/04/29/268052.html#Feedback" target="_blank" style="text-decoration:none;">鍙戣〃璇勮</a></div>]]></description></item><item><title>h:panelGrid 灞炴ц瑙?杞?http://m.tkk7.com/sealyu/archive/2009/04/24/267269.htmlsealsealFri, 24 Apr 2009 00:34:00 GMThttp://m.tkk7.com/sealyu/archive/2009/04/24/267269.htmlhttp://m.tkk7.com/sealyu/comments/267269.htmlhttp://m.tkk7.com/sealyu/archive/2009/04/24/267269.html#Feedback0http://m.tkk7.com/sealyu/comments/commentRss/267269.htmlhttp://m.tkk7.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 鏍囩瀛︿範
榪欎釜鏍囩鍙互鐢ㄦ潵浣滅畝鍗曠殑緇勪歡鎺掔増錛屽畠浼氫嬌鐢℉TML琛ㄦ牸鏍囩鏉ョ粯鍒惰〃鏍鹼紝騫跺皢緇勪歡緗簬鍏朵腑錛屼富瑕佹寚瀹歝olumns灞炴э紝渚嬪璁懼畾涓?2錛?
<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>
鍒欒嚜鍔ㄥ皢緇勪歡鍒嗕綔 2 涓?column鏉ユ帓鍒楋紝鎺掑垪鍑烘潵鐨勬牱瀛愬涓嬶細


<h:panelGrid>鐨勬湰浣撻棿鍙兘鍖呮嫭JSF緇勪歡錛屽鏋滄兂瑕佹斁鍏ラ潪JSF緇勪歡錛屼緥濡傜畝鍗曠殑鏍風増錛坱emplate錛夋枃瀛楋紝鍒欒浣跨敤 <f:verbatim>鍖呮嫭浣忥紝渚嬪錛?
<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>
榪欎釜緇勪歡鐢ㄦ潵灝嗘暟涓狫SF緇勪歡鍖呰璧鋒潵錛屼嬌鍏剁湅鏉ュ儚鏄竴涓粍浠訛紝渚嬪錛?
<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>錛岃繖浣垮緱< h:panelGrid>鍦ㄥ鐞嗘椂錛屽皢閭d袱涓?lt;h:commandButton>鐪嬩綔鏄竴涓粍浠舵潵鐪嬪緟錛屽叾瀹屾垚鐨勭増闈㈤厤緗涓嬫墍紺猴細


涓嬮潰杞澆涓巋ttp://blog.csdn.net/liyong1115/archive/2008/02/27/2125029.aspx
涓銆佸垵璇唒anelGrid鍜屼笌涔嬬浉鍏崇殑璁捐鍏冪礌

panelGrid鐩稿綋浜嶩TML鐨勮〃鏍鹼紝鍦ㄨ璁′腑涓庝箣鐩稿叧鐨勭粍浠舵湁panelGrop錛屼笌涔嬬浉閰嶅悎鐨凜SS

璁捐鍏冪礌鏈塻tyleClass銆乭eaderClass銆乫ooterClass銆乺owClasses銆乧olumnClasses銆傝繖浜涘厓

绱犵殑鏈夋満緇勫悎錛屽彲浠ヨ璁″嚭涓嶅悓鐨勮緭鍑虹敾闈€?

鍦℉TML緗戦〉璁捐涓紝琛ㄦ牸鏈?lt;table><tr><td>絳夋爣璁扮鍙鳳紝涔熷彲浠ュ湪鏍囪絎﹀彿鍐呭祵鍏SS鎺?

鍒惰鍙ユ潵鎺у埗杈撳嚭鐨勮〃鐜板艦寮忋侸SF涓殑panelGrid铏界劧涓嶩TML琛ㄦ牸鐩稿搴旓紝浣嗘槸浜岃呭湪璁捐鏃?

榪樻槸鏈夊緢澶у樊寮傜殑銆備緥濡傛垜浠亣璁炬湁涓涓狧TML鐨勮〃濡備笅錛?

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

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

鍒檖anelGrid涓庝箣瀵瑰簲鐨勬爣璁版槸錛?

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

</h:panelGrid>

瀹冨彧鏈夊澹蟲爣璁幫紝娌℃湁琛屾帶鍒跺拰鍒楁帶鍒舵爣璁般?

鐔熸倝HTML緙栫▼鐨勯亾浜轟竴鐪煎氨鐪嬪嚭錛屽彧鏈夊澹蟲爣璁幫紝浣犺鎬庢牱鎺у埗琛屾垨鍒楃殑杈撳嚭鏍峰紡鍛紵鍒?

鎬ワ紝JSF璁捐鑰呭凡緇忔兂鍒頒簡錛屼粬浠璁″嚭

浜唖tyleClass銆乭eaderClass銆乫ooterClass銆乺owClasses銆乧olumnClasses榪欎簺璁捐鍏冪礌鏉ユ帶

鍒惰涓庡垪鐨勮緭鍑烘牱寮忥紝鍏朵腑
styleClass鏄牸寮忚〃鏍兼葷殑澶栬鐨勶紝濡傝〃鏍肩殑闀夸笌瀹姐佸杈規鏍峰紡銆佽〃鏍肩殑鑳屾櫙鏍峰紡絳夈?
headerClass銆乫ooterClass鍒嗗埆鏄帶鍒惰〃鐨刪eader鍜宖ooter鐨勩?
rowClasses鍜宑olumnClasses鍒嗗埆鏄帶鍒惰〃鏍肩殑琛屼笌鍒楁牱寮忕殑銆?

榪樻槸涓句釜渚嬪瓙璇翠竴涓嬶紝鎴戜滑鏈変笅渚嬶細

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

<f:facet >
<h:outputText value="鎮ㄥソ錛屾湅鍙嬶紒"/>
</f:facet>

<h:outputText value="鎮ㄥソ錛屾湅鍙嬶紒"/>
<h:outputText value="鎮ㄥソ錛屾湅鍙嬶紒"/>
<h:outputText value="鎮ㄥソ錛屾湅鍙嬶紒"/>
<h:outputText value="鎮ㄥソ錛屾湅鍙嬶紒"/>
<h:outputText value="鎮ㄥソ錛屾湅鍙嬶紒"/>
<h:outputText value="鎮ㄥソ錛屾湅鍙嬶紒"/>

<f:facet >
<h:outputText value="鎮ㄥソ錛屾湅鍙嬶紒"/>
</f:facet>
</h:panelGrid>

榪欏氨鏄竴涓〃鏍鹼紝columns="1"錛岃瀹氳繖涓〃鍙湁涓鍒楋紝cellpadding="5"璇存槑浜嗚竟妗嗗綰?

涓庡唴綰跨殑璺濈鏄?涓儚绱犮傝繖涓〃鐢變竴涓ご閮ㄣ佷竴涓熬閮ㄥ拰涓棿琛ㄨ韓涓夐儴鍒嗙粍鎴愩俬eaderClass

鏄牸寮忓ご閮ㄦ牱寮忕殑錛宖ooterClass鏄牸寮忓熬閮ㄦ牱寮忕殑錛宺owClasses鍜宑olumnClasses鏄牸寮忚涓?

鍒楁牱寮忕殑銆?rowClasses="row1,row2"瑙勫畾浜嗚〃鏍肩殑琛屼笌琛屼氦鏇夸嬌鐢╮ow1鍜宺ow2鏍峰紡綾繪潵鏍煎紡

杈撳嚭鏍峰紡錛屽悓鏍鳳紝鍒椾篃鏄紝騫朵笖榪樺彲浠ョ敤3涓?涓垨鏇村涓猺ow3銆乺ow4...鏉ヤ緷搴忎氦鏇挎牸寮忚緭

鍑烘牱寮忋?

瀵瑰簲鐨勬牱寮忕被鍙互鍍忎互涓嬭繖鏍風紪鍐欏湪css鏂囦歡涓細


/*styleClass澶勪簬鐖剁被鐨勫湴浣?headerClazz,rowClasses絳夌殑瀛椾綋璁劇疆鍙杄m鏃?
鍏跺湪灞忓箷涓婃樉紺虹殑澶у皬浼氬弬鐓ц綾誨瓧浣撶殑澶у皬璁劇疆鑰屾斁澶ф垨緙╁皬*/

.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涓畾涔?
鍦╮owClasses涓畾涔変笉璧蜂綔鐢?
*/

.row1{
background-color:#FFFFFF;
}

.row2{
background-color:#C9D3E0;
}

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

.column2{
}


浣犲彲浠ョ敤CSS鍦↗SP涓殑璇硶灝嗗叾緙栧啓鍦↗SP鏂囦歡涓?

浜屻乸anelGrid濡備綍鏉ユ牸寮忔垚鍏鋒湁鎷嗗垎鍚堝茍鏍峰紡鐨勮〃

榪欒鐢ㄥ埌panelGroup錛屽畠鐨勪綔鐢ㄦ槸灝嗗皝瑁呭湪鍐呯殑鍏冧歡浣滀負涓涓厓浠舵潵鐪嬪緟錛屽鏋減anelGroup

涓皝瑁呬簡涓涓猵anelGrid錛屽垯琚皝瑁呯殑琛ㄦ斁鍦ㄥ叾浠栬〃涓氨鐩稿綋浜庝竴涓瓙琛ㄣ傞氳繃panelGroup鏉ュ皝

瑁呭悇UI緇勪歡鐨勫姙娉曪紝鍙互瀹炵幇琛ㄦ牸鐨勬媶鍒嗙洰鐨勩?

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

鎴栬咃細

<h:panelGroup>
<h:outputText value="鎮ㄥソ錛屾湅鍙嬶紒"/>
<h:outputText value="鎮ㄥソ錛屾湅鍙嬶紒"/>
</h:panelGroup>

瀹冧滑鍦ㄥ鍣ㄤ腑鐩稿綋浜庝竴涓樉紺哄厓浠?濂藉儚鏈潵鏄竴涓漢浣忎竴闂存埧錛岀幇鍦ㄦ槸鏇村鐨勪漢浣忎竴闂存埧)銆?

涓夈佸浣曞湪panelGrid涓疄鐜拌璁″厓绱犲榻?

panelGrid鏄氳繃CSS璇█鏉ユ牸寮忚緭鍑烘牱寮忕殑錛屽湪CSS璇█涓彲鐢╲ertial-align:...;鏉ユ牸

寮忚緭鍑哄厓绱犵旱鍚戝榻愶紝浣跨敤text-align:...;鏉ュ疄鐜拌緭鍑哄厓绱犳í鍚戝榻愩傚叾涓璽ext-align鏈夌偣

榪風硦浜猴紝鍥犱負浠庡瓧闈㈢湅瀹冨簲璇ユ槸閽堝鏂囨湰鐨勶紝鍏跺疄瀹冨鍏朵粬鍏冪礌涔熻搗浣滅敤銆?

鍦ㄥ榻愮殑璁捐涓湁涓眳涓榻愮殑闂瀹規槗緇曚漢銆傚湪HTML涓彲鐢?lt;center>...</center>鏉ュ疄

鐜拌灝佽鐨勮鍥懼厓绱犲眳涓紝浣嗗湪CSS涓ソ鍍忔病鏈夌被浼艱鍙ャ傚叾瀹炶繕鏄湁鐨勶紝鍙笉榪囩粫浜嗕竴涓集

銆備綘鎯沖晩錛岃鍒板眳涓紝閭g┒绔熸槸鍦ㄥ瀹界殑鑼冨洿鍐呭眳涓紵鏄垜榪欎釜鍏冪礌鍦ㄥ皝瑁呮垜鐨勫鍣ㄤ腑灞呬腑錛?

榪樻槸琚垜灝佽鐨勫厓绱犲湪鎴戣繖涓鍣ㄤ腑灞呬腑錛熻繖涓棶棰楥SS涓嶩TML澶勭悊璇箟鏄笉鏍風殑銆?

鍦℉TML涓〃鏍煎眳涓槸錛?
<table align="center">
...
</table>

琛ㄦ牸鍦ㄨ繖閲岀殑灞呬腑鏄寚榪欎釜琛ㄦ牸“鎴?#8221;鍦ㄥ皝瑁呮垜鐨勫鍣?lt;body>涓眳涓紝鍏蜂綋琛ㄧ幇涓哄湪灞忓箷涓婂眳

涓紝浣嗘槸鎮ㄤ笉鑳介氳繃

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

鏉ュ疄鐜皃anelGrid鍦?lt;body>涓眳涓傚洜涓簆anelGrid鏍囪鏍規湰涓嶆敮鎸佽繖涓鍙ャ傝繕鏄閫氳繃CSS

鏉ュ疄鐜般備笅闈㈣繖涓嬌鐢–SS璇彞鎻忚堪灞呬腑鐨勮涔変笌HTML浣跨敤align="center"璇箟涓嶅悓銆?

<h:panelGrid style="text-align:center">
<h:outputText value="鎮ㄥソ錛屾湅鍙嬶紒"/>
</h:panelGrid>

榪欎釜璇彞璇寸殑鏄痬e榪欎釜瀵硅薄鍦╬anelGrid 涓眳涓紝鑰屼笉鏄寚琛ㄦ牸鍦?lt;body>(灞忓箷)涓眳涓傛垜

瑕佸湪灞忓箷涓眳涓庝箞鍔烇紵鏈変袱縐嶅姙娉曪紝涓縐嶆槸閫氳繃鍦?lt;body>涓姞鍏ユ牸寮忚鏄庯紝絎簩縐嶅姙娉曟槸鍦?

panelGrid鐨勫闈㈠啀濂椾竴涓猵anelGrid銆傚嵆錛?


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

<h:panelGroup>
<h:panelGrid style="text-align:center">
<h:outputText value="鎮ㄥソ錛屾湅鍙嬶紒鎮ㄥソ錛屾湅鍙嬶紒"/>
<h:outputText value="鎮ㄥソ錛屾湅鍙嬶紒"/>
<h:outputText value="鎮ㄥソ錛屾湅鍙嬶紒"/>
</h:panelGrid>
</h:panelGroup>

</h:panelGrid>

榪欐牱灝卞疄鐜頒簡琚皝瑁呯殑panelGrid B 鍦?A 涓眳涓紝娉ㄦ剰錛岃繖閲岀殑width=979px;鏄繀欏葷殑錛屽畠

瑙勫畾浜嗗眳涓槸鍦ㄥ瀹界殑鑼冨洿鍐呭眳涓紒鏁板瓧澶氬皯鍙互璋冩暣錛屼絾鏄綘涓嶈兘涓嶅啓榪欎釜綰﹀畾錛屽惁鍒欙紝琚?

灝佽鍦ㄩ噷闈㈢殑panelGrid榪樻槸涓嶄細鍦ㄥ睆騫曚笂灞呬腑銆?

榪樻湁涓鐐規敞鎰忥紝閲岄潰panelGrid B 鐨則ext-align緇ф壙澶栭潰panelGrid A 涓殑text-align灞?

鎬х殑綰﹀畾錛屽嵆閲岄潰鐨刾anelGrid涓嶅啓style="text-align:center"錛屽璞e浠篃浼氬湪閲?

闈anelGrid涓眳涓備絾鏄噷闈㈢殑panelGrid涓嶇戶鎵垮闈㈢殑width錛屽儚涓婇潰錛岄噷闈anelGrid鐨勬樉

紺哄搴︿笌鏈闀跨殑me1鏈夊叧錛岃屼笉鏄闈anelGrid A鐨勫搴?79px銆?

鍥涖佸叾浠?
鈻犲綋灞忓箷鐨勬樉寮忔牸寮忔槸1024 X 768 鏃訛紝鏈澶栭潰鐨刾anelGrid瀹藉害鍙?79px鏄睆騫曟渶澶у寲鏃?

搴曢儴婊氬姩鏉$敱鍑虹幇鍒頒笉鍑虹幇鐨勪復鐣屽鹼紝濡傝秴榪?79鍒欐粴鍔ㄦ潯灝變細鍑虹幇銆?
鈻犲彲浠ユ寜鐓ф槸瀵?lt;table><tr>榪樻槸瀵?lt;td>璧蜂綔鐢ㄧ殑CSS綾伙紝榪涜灝佽銆傚鍐欏湪style璇彞涓?

錛屽垯褰㈠涓嬶細

<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瀹夊叏絳栫暐錛堣漿錛?/title><link>http://m.tkk7.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://m.tkk7.com/sealyu/archive/2009/04/23/267164.html</guid><wfw:comment>http://m.tkk7.com/sealyu/comments/267164.html</wfw:comment><comments>http://m.tkk7.com/sealyu/archive/2009/04/23/267164.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/sealyu/comments/commentRss/267164.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/sealyu/services/trackbacks/267164.html</trackback:ping><description><![CDATA[<h2>鍘熷笘鍦板潃錛歨ttp://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://m.tkk7.com/sealyu/aggbug/267164.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/sealyu/" target="_blank">seal</a> 2009-04-23 15:36 <a href="http://m.tkk7.com/sealyu/archive/2009/04/23/267164.html#Feedback" target="_blank" style="text-decoration:none;">鍙戣〃璇勮</a></div>]]></description></item><item><title>Seam涓厤緗簨鍔$鐞嗗櫒錛圕onfiguring a Seam transaction manager錛?/title><link>http://m.tkk7.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://m.tkk7.com/sealyu/archive/2009/04/20/266600.html</guid><wfw:comment>http://m.tkk7.com/sealyu/comments/266600.html</wfw:comment><comments>http://m.tkk7.com/sealyu/archive/2009/04/20/266600.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/sealyu/comments/commentRss/266600.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/sealyu/services/trackbacks/266600.html</trackback:ping><description><![CDATA[鍘熷笘鍦板潃錛歨ttp://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://m.tkk7.com/sealyu/aggbug/266600.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/sealyu/" target="_blank">seal</a> 2009-04-20 20:10 <a href="http://m.tkk7.com/sealyu/archive/2009/04/20/266600.html#Feedback" target="_blank" style="text-decoration:none;">鍙戣〃璇勮</a></div>]]></description></item><item><title>JSF Validator(杞?http://m.tkk7.com/sealyu/archive/2009/04/14/265446.htmlsealsealTue, 14 Apr 2009 02:58:00 GMThttp://m.tkk7.com/sealyu/archive/2009/04/14/265446.htmlhttp://m.tkk7.com/sealyu/comments/265446.htmlhttp://m.tkk7.com/sealyu/archive/2009/04/14/265446.html#Feedback0http://m.tkk7.com/sealyu/comments/commentRss/265446.htmlhttp://m.tkk7.com/sealyu/services/trackbacks/265446.htmlJSF Validator鍏ラ棬鍩虹綃?- JSF Validator鐨勪粙緇嶄笌浣跨敤

JSF妗嗘灦鎻愪緵Validator鏈哄埗錛屽鐢ㄦ埛杈撳叆鍊肩殑鍚堟硶鎬ц繘琛岄獙璇併傝嫢鐢ㄦ埛杈撳叆鍊兼棤鏁堬紝榪樻彁渚涗簡閿欒娑堟伅鏄劇ず鍔熻兘錛屼互甯姪鐢ㄦ埛鑳芥紜緭鍏ャ?/span>

鍦ㄥ紑濮嬫湰鏂囦箣鍓嶏紝寤鴻闃呰涓嬮潰鐨勬枃绔狅細
娣卞叆浜嗚ВJSF
娣卞叆浜嗚ВJSF錛堜簩錛夛細浠嶫SF鐨凩ifecycle鐪婮SF瀵歸〉闈㈢殑澶勭悊鏈哄埗鍜屾祦紼?/strong>
浠ヤ簡瑙SF鐨勬蹇電瓑銆?br />
JSF Validator鍥撅細


JSF Validator鐗圭偣錛?/div> 杈撳叆鏁版嵁鐨勯獙璇佹斁鍦ㄦ湇鍔″櫒绔繘琛屻?br /> 闇瑕侀獙璇佽緭鍏ュ肩殑緇勪歡錛堣緭鍏ョ粍浠訛級鍦↗SP閲岄氳繃JSF鏍囩鍔犱互璁劇疆錛屾柟娉曠畝鍗曠洿瑙傘?br /> 姣忎釜杈撳叆緇勪歡鍙互鍚屾椂緇戝畾澶氫釜Validator銆?br /> 楠岃瘉鍙戠敓閿欒鏃訛紝鍙互鍚慒acesContext鐧誨綍閿欒淇℃伅錛屽茍涓斿彲浠ラ氳繃JSP鐩存帴鏄劇ず銆傛樉紺洪鏍間笌浣嶇疆鍙互鑷敱璁懼畾銆?br /> 楠岃瘉閿欒鏃訛紝JSF鐨勭敓鍛藉懆鏈熸帶鍒舵満鍒惰嚜鍔ㄤ腑姝㈠鐞嗘祦紼嬶紝璺寵漿鍒扮敾闈㈡弿鐢婚樁孌碉紙Render Response Phase錛夈?br /> JSF鏍囧噯鎻愪緵瀵規暟鍊鹼紙long, double錛夌殑鏈澶ф渶灝忓奸獙璇侊紝鏂囧瓧鍒楃殑鏈澶ф渶灝忛暱搴﹂獙璇侊紝浠ュ強蹇呴』(required)楠岃瘉絳塚alidator銆?br /> 鏀寔鐢ㄦ埛鑷畾涔塚alidator銆傜敤鎴瘋嚜瀹氫箟Validator鐨勬柟娉曟湁2縐嶏紝涓縐嶆槸Method Validator錛屼竴縐嶆槸瀹炵幇javax.faces.validator.Validator鎺ュ彛銆傛湰鏂囩殑鍚庨潰灝嗗鍏朵綔璇︾粏浠嬬粛銆?br />

JSF鏍囧噯Validator

validateDoubleRange


Validator鏍囩鍚嶏細f:validateDoubleRange鏍囩銆?br />   灞炴у悕錛?br />       maximum="鏈澶у?
      minimum="鏈灝忓?
Validator ID錛歫avax.faces.DoubleRange
Validator 綾伙細javax.faces.validator.DoubleRangeValidator
杈撳叆鍊肩殑鑼冨洿楠岃瘉銆?br /> 杈撳叆鍊煎繀欏諱負Number錛堟暟鍊鹼級綾誨瀷鎴栬呭彲浠ヨ漿鎹負Double綾誨瀷鐨勫?br />

validateLongRange


Validator鏍囩鍚嶏細f:validateLongRange
  灞炴у悕錛?br />       maximum="鏈澶у?
      minimum="鏈灝忓?
Validator ID錛歫avax.faces.LongRange
Validator 綾伙細javax.faces.validator.LongRangeValidator
杈撳叆鍊肩殑鑼冨洿楠岃瘉銆?br /> 杈撳叆鍊煎繀欏諱負Number錛堟暟鍊鹼級綾誨瀷鎴栬呭彲浠ヨ漿鎹負Long綾誨瀷鐨勫?br />

validateLength


Validator鏍囩鍚嶏細f:validateLength
  灞炴у悕錛?br />       maximum="鏈澶у?
      minimum="鏈灝忓?
Validator ID錛歫avax.faces.Length
Validator 綾伙細javax.faces.validator.LengthValidator
杈撳叆鍊肩殑闀垮害楠岃瘉銆?br /> 杈撳叆鍊煎繀欏諱負String錛堝瓧絎︿覆錛夋垨鑰呭彲浠ヨ漿鎹負String綾誨瀷鐨勫?br />

JSF required錛堝繀欏昏緭鍏ワ級 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> 鍚勮緭鍏ョ粍浠朵嬌鐢╮equired validator鐨勬柟娉曚笂闈㈠凡緇忎綔浜嗕粙緇嶏紝榪欓噷涓嶅啀閲嶅銆?br />

浣跨敤Method Validator


JSF鏀寔Method綰у埆鐨刅alidator錛岃繖縐峍alidator瀹炵幇璧鋒潵姣旇緝綆鍗曪紝鍙互鍦ㄤ換浣旿SF鐨刴anaged-bean閲屽疄鐜頒竴涓被浼間互涓嬬殑鏂規硶錛?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. }  

鍏朵腑錛宑ontext鍙橀噺涓篔SF瀹瑰櫒涓婁笅鏂囩幆澧冿紝component涓? 緇戝畾鐨勭粍浠訛紝value涓虹粍浠剁殑杈撳叆鍊箋倂alidateXxxx鍙互涓轟換鎰忎綘鍠滄鐨勬柟娉曞悕銆備笌棰勬湡鐨勮緭鍏ュ間笉絎﹀悎鐨勮瘽錛屽彲浠ラ氳繃throw涓涓? ValidatorException銆?some message"渚挎槸鎯寵鏄劇ず鐨勯敊璇秷鎭?br />
鐒跺悗鍦↗SP涓細
  1. <h:inputText value="#{mybean.someValue}" validator="#{mybean.validateXxxx}"/>  

渚垮彲銆?br /> 閿欒娑堟伅鐨勬樉紺虹◢鍚庡啀浣滀粙緇嶃?br />

Validator鏍囩鐨勪嬌鐢?/h3>
Validator鏍囩鍙互鎺ユ敹鍙傛暟錛屾墍浠ュ姛鑳戒笂姣旇緝寮哄ぇ錛屼篃姣旇緝鐏墊椿銆傚悓鏃訛紝闄や簡浣跨敤JSF鏍囧噯鐨刅alidator鏍囩涔嬪錛屼綘榪樺彲浠ヨ嚜瀹氫箟Validator鏍囩銆傚叧浜庤嚜瀹氫箟Validator鏍囩鎴戜滑灝嗗湪鍙﹀鐨勬枃绔犱腑鍔犱互浠嬬粛銆?br /> Validator鏍囩鐨勪嬌鐢ㄤ緥錛?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涓簒xxxValue鐨勮緭鍏ユ緇勪歡鐨勮緭鍏ュ煎仛double鑼冨洿楠岃瘉錛屾寚瀹氳寖鍥存渶澶у間負5銆傝秴榪?鐨勬儏鍐靛垯鏄劇ず閿欒娑堟伅錛岄敊璇秷鎭彲浠ヤ嬌 鐢?lt;h:message />鎴栬?lt;h:messages />鏍囩鏄劇ず銆傛湁鍏蟲秷鎭鐞嗙殑璇︾粏浠嬬粛璇峰弬鑰冿細
JSF鍏ㄩ潰鐞嗚В涔嬫秷鎭鐞?/strong>
涓鏂?br />

f:validator鏍囩鐨勪嬌鐢ㄤ笌Validator ID


闄や簡浠ヤ笂2縐嶉獙璇佹柟娉曚箣澶栵紝榪樺彲浠ヤ嬌鐢╢:validator鏍囩瀵硅緭鍏ュ煎姞浠ラ獙璇併俧:validator鏍囩闇瑕佹寚瀹歷alidatorId灞炴э紝Validator Id闇瑕佸湪faces-config.xml閰嶇疆鏂囦歡涓姞浠ラ厤緗?br />

f:validator鏍囩鐨勪嬌鐢ㄤ緥錛?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 ID錛屾垜浠皢鍦ㄨ嚜瀹氫箟Validator鏍囩涓鏂囦腑瀵筕alidator ID鍋氳緇嗕粙緇嶃?br />
JSF妗嗘灦灝嗚皟鐢ㄦ寚瀹歏alidator ID鎵瀵瑰簲鐨刅alidator鐨?br /> public void validate(FacesContext context, UIComponent component, Object value)
鏂規硶銆?br />
璺烳ethod Validator涓鏍鳳紝涓嶈兘f:validator鏍囩浼犲叆鍙傛暟銆?br />
鏈枃浠嬬粛浜咼SF Validator鐨勬満鍒訛紝鐗圭偣錛岀綾伙紝浠ュ強浣跨敤鏂規硶絳夈傛垜浠皢鍦ㄨ繎鏈熷叾瀹冩枃绔犱腑浠嬬粛鎬庝箞鑷畾涔塚alidator銆?br />

JSF Validator榪涢樁綃?- 鑷畾涔塉SF Validator


JSF妗嗘灦鎻愪緵Validator鏈哄埗錛屽鐢ㄦ埛杈撳叆鍊肩殑鍚堟硶鎬ц繘琛岄獙璇併傝嫢鐢ㄦ埛杈撳叆鍊兼棤鏁堬紝榪樻彁渚涗簡閿欒娑堟伅鏄劇ず鍔熻兘錛屼互甯姪鐢ㄦ埛鑳芥紜緭鍏ャ?/span>


鍦?JSF Validator鍏ラ棬鍩虹綃?- JSF Validator鐨勪粙緇嶄笌浣跨敤  涓鏂囦腑鎴戜滑浠嬬粛浜咼SF Validator鐨勬満鍒訛紝鐗圭偣錛岀綾伙紝浠ュ強浣跨敤鏂規硶絳夈?br />
鏈枃灝嗕粙緇嶆庝箞鑷畾涔塚alidator鍜孷alidator鏍囩銆?br />
鑷畾涔塚alidator鏈?縐嶆柟娉曪細涓縐嶆槸Method Validator錛屾垜浠湪JSF Validator鍏ラ棬鍩虹綃?- JSF Validator鐨勪粙緇嶄笌浣跨敤  涓鏂囦腑宸蹭綔浜嗕粙緇嶏紝榪欓噷涓嶅啀璇﹁堪錛涘彟涓縐嶆槸閫氳繃瀹炵幇Validator鎺ュ彛錛屼篃灝辨槸浣跨敤鑷畾涔夌殑Validator綾匯?br />
鑷畾涔塚alidator綾諱笌Validator鏍囩鏈変互涓嬪嚑涓楠わ細
鑷畾涔塚alidator綾葷殑瀹炵幇
faces-config.xml鐧誨綍
鑷畾涔塚alidator鏍囩綾?br /> 璁劇疆TLD鏂囦歡


鑷畾涔塚alidator綾葷殑瀹炵幇
瀹氫箟涓涓被錛岃綾誨疄鐜癹avax.faces.validator.Validaotr鎺ュ彛錛?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.     ... //鍏跺畠鍙傛暟璁劇疆錛屾柟娉曠瓑錛堢暐錛?nbsp; 
  16. }  


faces-config.xml鐧誨綍
鑷畾涔塚alidator綾諱箣鍚庯紝榪樺緱鍚慺aces-config.xml鐧誨綍涔嬪悗鎵嶈兘浣跨敤銆?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>  


緇忚繃涓婇潰2涓楠わ紝灝卞彲浠ヤ嬌鐢∕yValidator浜嗐?br /> 渚嬶細
<h:inputText id="xxxxValue" value="#{mybean.xxxxValue}">
  <f:validator validatorId="MyValidator"></f:validator>
</h:inputText>

鑷畾涔塚alidator鏍囩綾?/div> 涓婇潰鐨凪yValidator铏界劧鍙互閫氳繃f:validator鏍囩鍔犱互鍒╃敤錛?浣嗕笉鑳藉悜鍏朵紶鍏ュ弬鏁幫紝鑻ヨ鍚戝叾浼犲叆鍙傛暟錛屽垯闇瑕佸畾涔夎嚜瀹氫箟Validator鏍囩綾匯?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. }  

鍙﹀錛屼負MyValidator.java鍔犲叆鐩稿簲鍙傛暟鍙婃柟娉曞疄鐜般?br />
TLD鏂囦歡
瀹氫箟濂絍alidator鏍囩綾諱箣鍚庯紝榪橀渶瑕佸湪TLD鏂囦歡璁劇疆錛屾湁鍏砊LD榪欓噷灝變笉浠嬬粛浜嗐傝澶у鍙傝冪浉鍏寵祫鏂欍?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>  


鑷畾涔塚alidator鏍囩鐨勪嬌鐢?/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鏂版墜蹇呰錛堣漿錛?/title><link>http://m.tkk7.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://m.tkk7.com/sealyu/archive/2009/04/13/265298.html</guid><wfw:comment>http://m.tkk7.com/sealyu/comments/265298.html</wfw:comment><comments>http://m.tkk7.com/sealyu/archive/2009/04/13/265298.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/sealyu/comments/commentRss/265298.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/sealyu/services/trackbacks/265298.html</trackback:ping><description><![CDATA[ 鍘熷笘鍦板潃錛歨ttp://blog.csdn.net/bq_cui/archive/2007/03/21/1536706.aspx<br /> <br /> 寮濮嬪涔爏eam鐨勬椂鍊欙紝鏈変袱涓棶棰橈細鎴戜細鐢⊿pring鍜孒ibernate錛屼絾涓鐐逛篃涓嶆噦Seam 鍜孍JB3鐨?EntityManager銆傛垜鐢ㄤ簡涓浜涙椂闂村涔爏eam錛屼絾EntityManager 涓鐩村洶鎵版垜銆?span><br />     鍚屾椂鎴戜篃鏈変簡涓浜涘皬鏀惰幏錛屾効鎰忚窡鍒氬垰寮濮嬪涔爏eam鐨勬湅鍙嬪垎浜互涓嬨傚埆绱у紶錛屾垜涓嶆暍紜俊鎴戝啓鐨勪笢瑗塊兘姝g‘ ;). <br />     濂戒簡錛屽叧浜嶦ntityManager鏈変綍鐢ㄥ錛熷畠綆$悊浣犵殑entities ;)銆?閭f槸涓浜涚畝鍗曠殑java瀵硅薄錛岄氳繃getters and setters鍏峰涓浜涘睘鎬с傝繖浜涘睘鎬т箣涓鏄痠d錛堜竴鑸槸Long鏁版嵁綾誨瀷錛夛紝騫朵笖榪欎簺class蹇呴』浠Entity娉ㄨВ(annotated )銆傚湪seam鐨勬簮鐮佷腑鍙互鎵懼埌涓澶ф壒榪欐牱鐨勪緥瀛愶紝渚嬪booking渚嬪瓙銆傚湪seam涓紝涓浠跺緢閲嶈鐨勪簨鎯呭氨鏄紝姣忎釜Entity閮芥湁涓涓? @Name 娉ㄨВ(annotation)錛岃繖鏍鳳紝瀹冧滑鎵嶈兘琚敞鍏ュ埌鍏朵粬seam閮ㄤ歡(component)涓?br /> </span>    鍋囪鎴戜滑鏈夎繖鏍蜂竴涓猠ntity class錛屽彨鍋?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 鎻愪緵浜嗚繖浜涘姛鑳姐傞鍏堬紝濡備綍鎶奅ntityManager 寮曞叆鎴戠殑浠g爜錛熷緢綆鍗曪細</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;">    濂戒簡錛屾垜浠湅鐪嬩竴涓狤ntity 榪涚▼濡備綍浜х敓錛?/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;">    榪欏緢綆鍗曘傜幇鍦紝榪檈ntity 鐨勭姸鎬佹槸<span style="font-weight: bold;">NEW/TRANSIENT 銆傝繖鎰忓懗鐫涓涓猠ntity宸茬粡瀛樺湪浜庝綘鐨勫簲鐢ㄧ▼搴忎腑錛屼絾騫朵笉鍏鋒湁id錛屼篃涓嶅瓨鍦ㄤ簬浣犵殑鏁版嵁搴撲腑銆?br /> <br />     鐢變簬鎴戜滑瑕佷嬌瀹冩寔涔呭寲錛堝嵆瀹冨簲琚啓鍏ユ暟鎹簱錛夛紝鎴戜滑搴旀妸瀹冪殑鐘舵佽漿鎹負<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>    鐜板湪錛屾entity鐢盓ntityManager綆$悊浜嗐侲ntityManager鎺у埗entity鍐欏叆鏁版嵁搴撱傝繖鍔ㄤ綔鏃犻』绔嬪埢鍙戠敓錛屽彲鑳芥妸浣犵殑entity鏀懼湪cache錛岀◢鍚庡啓鍏ユ暟鎹簱銆備綘鍙互鏀懼績錛屽啓鍔ㄤ綔鑲畾浼氬彂鐢熴?br /> <br /> Ok, what about reading an existing entity from the database? Therefore we use: </p> <p>濂斤紝濡備綍浠庢暟鎹簱涓鍑哄凡瀛樺湪鐨別ntity鍛紵榪欐牱錛?/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 鏈変竴涓猧d錛堟垜宸茬粡璇磋繃錛屽鏁版儏鍐典笅鏄疞ong鏁版嵁綾誨瀷錛夛紝閫氳繃id浣犲彲瀛樺彇entity銆傝繖鏄繖閲岀殑絎簩涓弬鏁般傜涓涓弬鏁頒唬琛ㄤ綘瑕佸瓨鍙栫殑Entity class鐨勮繘紼嬨俧ind鎿嶄綔涔嬪悗錛宔ntity鐨勭姸鎬佷篃鏄?span style="font-weight: bold;">MANAGED 銆?/span></p> <p>涓鏃ntity鏁版嵁鏈夋墍鏀瑰彉錛屽皢鍙嶆槧鍒版暟鎹簱涓備笉鑳界‘璁ntityManager浣曟椂浼氬悜鏁版嵁搴撳啓鍏ユ洿鏂扮殑鏁版嵁銆備絾鏄繖涓浜嬩歡鑲畾浼氬彂鐢燂紝涓鑸槸椹笂錛屼絾涓嶄細鏅氫簬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>     榪欏皢寮哄埗EntityManager 绔嬪埢灝嗘洿鏂板啓鍏ユ暟鎹簱銆傝璁頒綇錛岃繖鏉¤鍙ュ皢褰卞搷鎵鏈夌姸鎬佷負<span style="font-weight: bold;">MANAGED鐨?/span>entitie錛岃屼笉鏄綋鍓嶄竴涓備笉榪囷紝涓鑸儏鍐典笅涓嶅繀榪欎箞鍋氥?br />     濡傛灉浣犳兂鍙嶅叾閬撹岃涔嬶紝涔熷氨鏄粠鏁版嵁搴撹澆鍏ヤ竴涓?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.refresh(entity);    </span></div> </div> <br /> </span><span>    鎬庢牱鍒犻櫎涓涓猠ntity鍛紵寰堢畝鍗曪細<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>    鐜板湪錛宔ntity鐨勭姸鎬佹垚涓?span style="font-weight: bold;">REMOVED錛岃〃紺哄叾宸茬粡琚垪鍏ュ垹闄よ鍒掋備綘鍙互鐢?/span>flush()璇彞錛岃鍒犻櫎鍔ㄤ綔椹笂鍙戠敓錛屼絾娌″繀瑕佽繖涔堝共銆?br /> <br />     鐜板湪鏉ョ偣澶嶆潅鐨勩傚綋娉ㄥ叆EntityManager 鐨勬椂鍊欙紝鏈変竴涓?span style="font-weight: bold;">浜嬪姟鑼冨洿鎸佷箙涓婁笅鏂囷紙</span><span style="font-weight: bold;"> Transaction Scoped Persistence Context</span>錛夈傚綋entitie澶勫湪MANAGED鐘舵佹椂錛屽叾澶勫湪鎸佷箙涓婁笅鏂囷紙persistence context 錛夌殑“瀹瑰櫒”涓?#8220;浜嬪姟鑼冨洿”鎰忓懗浠涔堬紵棣栧厛錛屼粈涔堟槸“浜嬪姟”錛?br /> <br />     EJB3Stateful 鍜?Stateless beans (渚濆悓鍚嶆爣娉ㄨ鯨鍒?鐨勬瘡涓柟娉曡皟鐢ㄩ兘鍖呰鍒頒竴涓簨鍔″唴銆傦紙欏轟究璇翠竴涓嬶紝浜嬪姟涓鏃﹀彂鐢烺untimeException錛屽嵆鍙戠敓浼氭粴錛屽鏁版嵁鐨勬敼鍙樺皢鎾ら攢錛夈傚洜姝わ紝鎸佷箙涓婁笅鏂囷紙persistence context錛夊皢鍦ㄨ皟鐢ㄦ柟寮忎箣鍓嶅緩绔嬶紝鏂瑰紡璋冪敤緇撴潫鍚庣Щ闄ゃ傜劧鍚庯紝鎸佷箙涓婁笅鏂囦腑綆$悊鐨勬墍鏈塭ntity鐨勭姸鎬佹垚涓?span style="font-weight: bold;"> DETACHED銆?/span><br /> <br />     鍋囪鍦ㄤ綘鐨刡ean閲屽ご鏈変袱涓猰ethod銆傜涓涓槸load(), 瀹冭皟鐢╢ind鍑芥暟鍙栧嚭鏁版嵁搴撲腑鐨勪竴涓疄浣撱傜浜屼釜鏄痜inish()錛岃繑鍥炰竴涓狫SF杈撳嚭銆傝皟鐢ㄨ繖涓や釜鍑芥暟涓棿淇敼浜嗗疄浣撴暟鎹傝繖縐嶄慨鏀規寔涔呭埌鏁版嵁搴撲腑鍚楋紵鍥炵瓟鏄細NO銆?br /> <br />     load() 鍑芥暟緇撴潫鍚庯紝EntityManager'鐨勬寔涔呬笂涓嬫枃緇撴潫錛屽畠鎵鏈夌鐞嗚繃鐨別ntity鐘舵佹垚涓篋ETACHED銆備竴涓悗鏋滄槸錛屼笌鏂癳ntity鐩稿弽-鏈変竴涓狪D錛屼絾浠栦滑鐨勭姸鎬佸茍涓嶆槸managed 錛屽榪欎簺detached entities 鎵浣滅殑鏇存柊騫朵笉褰卞搷鏁版嵁搴撱傚鏋滀綘鎯充嬌涓涓猠ntity 鏇存柊鏁版嵁搴擄紝闇瑕佸皢鍏墮噸鏂癮ttach鍒版寔涔呬笂涓嬫枃銆傚湪榪欎釜渚嬪瓙涓紝鍦?span>finish()鏂規硶涓鍔犱互涓嬭錛?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 />     鐜板湪榪欎釜entity 宸茬粡鍚堝茍鍒癴inish()鏂規硶鐨勬寔涔呬笂涓嬫枃涓?璁頒綇錛屾瘡涓柟娉曟槸涓涓簨鍔★紝姣忎釜浜嬬墿鏈夎嚜宸辯殑鎸佷箙涓婁笅鏂?錛屽茍涓旂姸鎬佹槸鍙堝彉涓簃anaged銆?br /> <br />      榪欐牱鍋氭槸鍙互鐨勶紝浣嗘湁涓や釜緙虹偣錛?br /> -闇瑕佽皟鐢╩erge(->澶氫簡涓浜涗唬鐮?<br /> -璋冪敤find()涔嬪墠錛屽鏋滄煇涓猠ntity鏈垵濮嬪寲錛岃屼綘鍙堣瀛樺彇瀹冪殑鏌愪簺灞炴э紝灝嗕細寰楀埌exception 閿欒銆?br /> <br />     鏈変竴涓畝鍗曠殑瑙e喅鏂規錛氭墿灞曟寔涔呬笂涓嬫枃鐨勭敓鍛芥湡錛岃繖鏍鳳紝褰撹皟鐢ㄥ涓簨鍔?鏂規硶鏃訛紝entity鐘舵佸緇堜繚鎸佷負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 />      鐜板湪錛宮anaged entities "鐢熸椿鍦?涓涓墿灞曟寔涔呬笂涓嬫枃涓? <span style="font-weight: bold;">Extended Persistence Context </span>)銆?br /> <br />     浣犵敋鑷蟲棤欏誨懠鍙玬erge()鏂規硶錛屽洜涓篹itities浠庢湭琚獶ETACHED銆備綘鍙兘浼氶棶錛氭櫘閫氫簨鍔¤寖鍥達紙 "normal" (transaction scoped) 錛夋寔涔呬笂涓嬫枃鐨勫ソ澶勬槸浠涔堬紵瀹冧竴鐩翠緷闄勪簬浣犲仛鐨勪簨鎯咃紙灝忓磾錛氫粈涔堟剰鎬濓紵錛夈傛墿灞曚笂涓嬫枃闇瑕佹洿澶氱殑鍐呭瓨錛屽洜涓哄嵆浣夸綘涓嶉渶瑕侊紝瀹冧篃涓鐩村瓨鍦ㄤ簬鍐呭瓨銆傚茍涓斾竴鏃ntities琚叾浠栫殑bean鏀瑰彉錛堝畠浠湁鑷繁鐨勬寔涔呬笂涓嬫枃錛夛紝浣犻渶瑕佹樉寮忓湴璋冪敤refresh()鏂規硶錛堝湪overviews/list欏甸潰錛夈傚綋浣犻渶瑕佹櫘閫欵ntityManager 鏃跺畠灝卞湪閭i噷錛屽洜鍏剁敓鍛藉懆鏈熺煭錛屽彧鑳芥搷浣滃嵆鏃舵暟鎹?) <br /> <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;">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 />     榪欎笉鏄?#8220;鐪熸”SQL錛岃屾槸綾諱技sql鐨勪笢瑗匡紝縐頒箣涓?span>EJBQL銆備綘鍙互鐢ㄥ畠鎵ц鏌愪簺鏉′歡鏌ヨ錛屾帓搴忕瓑錛屽<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>    浠呬嬌鐢╡ntity灞炴у悕縐板嵆鍙傚叧浜嶦JBQL 瑕佽鐨勫お澶氫簡錛屼絾瀵逛簬鏈瘒浠嬬粛鏉ヨ榪欏凡瓚沖銆?br /> <br />     濂斤紝鍩烘湰浠嬬粛鍒版涓烘銆傚笇鏈涘浣犳潵璇達紝鍦ㄥ浣曚嬌鐢‥ntityManager鏂歸潰錛岃繖涓涓畝鍗曟槗鎳傜殑浠嬬粛銆?br /> <br />     鎴戝凡澹版槑榪囷紝涓嶈兘淇濊瘉鐧懼垎鐧炬紜傚茍涓旇偗瀹氭湁璁稿鑻辮璇硶閿欒(瀵逛笉璧鳳紝鎴戞槸寰峰浗浜猴紝涓嶈鎵撴垜PP鍣?銆傛榪庢枾姝c?br /> <br /> <br /> 2007.4.11緲昏瘧鑷細<br /> http://www.jboss.com/index.html?module=bb&op=viewtopic&t=88460</p> </span> <img src ="http://m.tkk7.com/sealyu/aggbug/265298.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/sealyu/" target="_blank">seal</a> 2009-04-13 15:34 <a href="http://m.tkk7.com/sealyu/archive/2009/04/13/265298.html#Feedback" target="_blank" style="text-decoration:none;">鍙戣〃璇勮</a></div>]]></description></item><item><title>SEAM涓璊STL鏍囩鍜寀i鏍囩鐨勬販鍚堜嬌鐢?c:forEach vs ui:repeat)http://m.tkk7.com/sealyu/archive/2009/04/13/265212.htmlsealsealMon, 13 Apr 2009 00:52:00 GMThttp://m.tkk7.com/sealyu/archive/2009/04/13/265212.htmlhttp://m.tkk7.com/sealyu/comments/265212.htmlhttp://m.tkk7.com/sealyu/archive/2009/04/13/265212.html#Feedback0http://m.tkk7.com/sealyu/comments/commentRss/265212.htmlhttp://m.tkk7.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://m.tkk7.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://m.tkk7.com/sealyu/archive/2009/04/09/264599.html</guid><wfw:comment>http://m.tkk7.com/sealyu/comments/264599.html</wfw:comment><comments>http://m.tkk7.com/sealyu/archive/2009/04/09/264599.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/sealyu/comments/commentRss/264599.html</wfw:commentRss><trackback:ping>http://m.tkk7.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://m.tkk7.com/sealyu/aggbug/264599.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/sealyu/" target="_blank">seal</a> 2009-04-09 10:54 <a href="http://m.tkk7.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://m.tkk7.com/sealyu/archive/2009/04/02/263588.htmlsealsealThu, 02 Apr 2009 09:42:00 GMThttp://m.tkk7.com/sealyu/archive/2009/04/02/263588.htmlhttp://m.tkk7.com/sealyu/comments/263588.htmlhttp://m.tkk7.com/sealyu/archive/2009/04/02/263588.html#Feedback0http://m.tkk7.com/sealyu/comments/commentRss/263588.htmlhttp://m.tkk7.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 鍙戣〃璇勮
]]>
鍦↗SF鍜孲EAM涓java.util.Set鍙婂叾瀛愮被浣滃驚鐜?/title><link>http://m.tkk7.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://m.tkk7.com/sealyu/archive/2009/04/01/263344.html</guid><wfw:comment>http://m.tkk7.com/sealyu/comments/263344.html</wfw:comment><comments>http://m.tkk7.com/sealyu/archive/2009/04/01/263344.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/sealyu/comments/commentRss/263344.html</wfw:commentRss><trackback:ping>http://m.tkk7.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://m.tkk7.com/sealyu/aggbug/263344.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/sealyu/" target="_blank">seal</a> 2009-04-01 13:47 <a href="http://m.tkk7.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"> <p>感谢您访问我们的网站,您可能还对以下资源感兴趣:</p> <a href="http://m.tkk7.com/" title="亚洲av成人片在线观看">亚洲av成人片在线观看</a> <div class="friend-links"> </div> </div> </footer> 主站蜘蛛池模板: <a href="http://6609929.com" target="_blank">最新国产乱人伦偷精品免费网站</a>| <a href="http://0354888.com" target="_blank">免费无码午夜福利片69</a>| <a href="http://sy8989.com" target="_blank">久久久久国产免费</a>| <a href="http://shandonghj.com" target="_blank">国产亚洲美女精品久久久久狼</a>| <a href="http://an930.com" target="_blank">亚洲免费日韩无码系列</a>| <a href="http://hdznzdh.com" target="_blank">亚洲精品无码久久久</a>| <a href="http://zdxxxx.com" target="_blank">日韩免费在线中文字幕</a>| <a href="http://www-84243.com" target="_blank">亚洲成年人啊啊aa在线观看</a>| <a href="http://se70me.com" target="_blank">国产精品亚洲天堂</a>| <a href="http://714747.com" target="_blank">亚洲毛片不卡av在线播放一区</a>| <a href="http://gbn21.com" target="_blank">特a级免费高清黄色片</a>| <a href="http://jinlaifubuxiugang.com" target="_blank">深夜国产福利99亚洲视频</a>| <a href="http://worldbiao.com" target="_blank">青青草国产免费国产是公开</a>| <a href="http://ss8kk.com" target="_blank">中文字幕无码精品亚洲资源网</a>| <a href="http://565636.com" target="_blank">精品国产污污免费网站入口</a>| <a href="http://taixin668.com" target="_blank">国产亚洲美日韩AV中文字幕无码成人</a>| <a href="http://gangxiangli.com" target="_blank">产传媒61国产免费</a>| <a href="http://s4lm0x.com" target="_blank">亚洲网站在线观看</a>| <a href="http://ipx588.com" target="_blank">中文字幕无码免费久久99</a>| <a href="http://livejimmy.com" target="_blank">亚洲乱妇熟女爽到高潮的片</a>| <a href="http://90hong.com" target="_blank">免费国产小视频在线观看</a>| <a href="http://gstywy.com" target="_blank">中国一级毛片免费看视频</a>| <a href="http://gstywy.com" target="_blank">香蕉视频在线观看亚洲</a>| <a href="http://conghui8.com" target="_blank">97热久久免费频精品99</a>| <a href="http://ding001.com" target="_blank">免费看a级黄色片</a>| <a href="http://shelaoban.com" target="_blank">成人一级免费视频</a>| <a href="http://ccc321.com" target="_blank">亚洲自偷精品视频自拍</a>| <a href="http://www026qqcom.com" target="_blank">免费观看男人免费桶女人视频</a>| <a href="http://fkg675.com" target="_blank">欧亚一级毛片免费看</a>| <a href="http://0755haoma.com" target="_blank">亚洲电影国产一区</a>| <a href="http://taoh2517.com" target="_blank">麻豆国产VA免费精品高清在线</a>| <a href="http://zhongxueping888.com" target="_blank">免费毛片毛片网址</a>| <a href="http://https357171.com" target="_blank">久久精品国产亚洲av影院</a>| <a href="http://0330196.com" target="_blank">在线观看视频免费国语</a>| <a href="http://anyliz.com" target="_blank">成人妇女免费播放久久久</a>| <a href="http://xyflash.com" target="_blank">亚洲国产av美女网站</a>| <a href="http://shyangpuks.com" target="_blank">亚洲精品国产自在久久</a>| <a href="http://wusongtv.com" target="_blank">亚洲电影免费观看</a>| <a href="http://35469642.com" target="_blank">免费人成视频在线播放</a>| <a href="http://w6626.com" target="_blank">亚洲制服丝袜一区二区三区</a>| <a href="http://53ggk.com" 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>