- 浏览: 164525 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
ooo456mmm:
正解~~~
无需安装oracle,配置plsql developer -
tjuking:
帮我解决了一大问题,thx~
vim批量修改文件 解决 非法字符: \65279 问题 -
dou85dou:
where is lz's content?
如何打造Linux下的IDE
zz from http://drewdev.blogspot.com/2008/03/build-time-vs-render-time.html
另 参考 http://news.sina.com.cn/pc/2009-11-13/326/1504.html
Build time vs. render time
Overview
There always seems to be someone posting about how MyFaces or JSF is "broken" and it turns out that they misused JSTL tags. No matter how many times a solution is posted, the issue comes up again. Therefore, I am writing this blog to help those that do not understand how facelets and JSP view handlers work.
The Problem
JSF works entirely differently than JSP. JSP, when used for JSF, is used to build a JSF component tree, not render a page. JSTL tags alter the contents of what is built, the component tree, not the HTML that is output by the component renderers.
A Background of JSP
JSP was written so that authoring servlets would be easier. JSP pages are servlets, nothing more. Using a JSP compiler, a JSP file is compiled into a Java Servlet. Before tag libraries were introduced, JSP pages simply were compiled down into System.out.println(...); statements.
Tag libraries enhanced JSP by providing an API to tag authors to write Java code that would not have to be embedded in <% ... %> tags. The tags gave developers access to the text content of the tag body so that they could alter it or use it in a custom way. After some time, Sun released the Java standard tag library API, also known as the JSTL.
The JSTL
The JSTL is a set of JSP tags to perform common JSP functionality (note that they are not related to JSF in any way at all). Many of them perform logic to alter their contents. In the case of c:if and c:choose, they choose which tag contents to be included in the response or not.
I will be mainly talking about the JSTL core tags in this article (catch, choose, forEach, forTokens, if, etc.). It is these that have such a profound, and often confusing to some people, affect on JSF.
What JSF Is
JSF is a component technology, and architecturally is not related to JSP at all. In fact, using JSP with JSF has drawbacks, included serious performance implications due to the architecture of JSP and how the JSP view handler works.
Note
Sun probably made the default view handler as one that uses JSP, so they would not have to admit that JSP did not meet the needs of users and needed to be replaced.
Component Technology
What I mean by JSF being a component technology, is that HTML is produced by the processing of a component tree by renderers. This design is much more similar to Swing than it is Servlets and JSP. Regardless of the view handler that is used, a tree of components is built.
Note
A component is simply a Java Object that implements the UIComponent interface, nothing more.
These components simply store attributes, have some behaviors and are similar in nature to the Swing Tree component. JSF relies on renderers (classes that extend Renderer) to produce content from the component tree. During the restore view, a JSF view should be restored to its previous state, so that it appears to code that there was never a round trip for the code to the client (this is important as I discuss the JSTL tags and especially c:forEach).
Note
Components do not have to use renderers to produce their content, but it is considered bad design to use the encode methods in a component to render a response.
Note
JSF is typically used to produce HTML, but can be used to generate any output that doesn't even have to be XML related, although the ResponseWriter's API is designed for XML content.
JSF with JSP
JSF is implemented using JSP by default (see my note above why this stinks). What this means is that JSP is used to build the JSF component tree. This is important to note because JSP is not used to generate any of the HTML, unlike a typical JSP page. There are two main stages of JSF on JSP:
Building of the component tree using JSP tags
Rendering of the component tree using the standard JSF lifecycle
Building of the component tree using JSP tags
As I mentioned earlier, JSF is a component technology. When JSP tags are used, instead of writing text (HTML) onto the servlet response, the tags create components and set attribute values on them. Most of this work is done by UIComponentClassicTagBase. The class hierarchy is:
java.lang.Object
javax.faces.webapp.UIComponentTagBase
javax.faces.webapp.UIComponentClassicTagBase
javax.faces.webapp.UIComponentELTag
javax.faces.webapp.UIComponentTag
The doStartTag method of UIComponentClassicTagBase calls findComponent, which despite its name creates the component (if needed) and calls setProperties. Therefore, the JSF component is created when the start of the JSP tag is processed. The setProperties method is responsible for setting the attributes of the component. Typically there is a one-to-one map of JSP tag attribute to JSF component attribute, so the setProperties simply copies the attributes over, doing any necessary conversion of the string value in the JSP attribute to an object that the component expects for the attribute.
How JSTL fits in
Most of the "work" of a component takes place during rendering. For example, the h:dataTable sets up the var attribute during rendering (and other phases too, but that is not pertinent to this article). This means that EL expressions that rely on variables that only have scope during the rendering phase are not valid during component creation. That is to say, there is no component lifecycle method for when the component is created.
Since JSTL tags are plain JSP tags and do not involve the JSF lifecycle, they do not have access to the environment that components create, like the var variable of an h:dataTable. Take this code for example:
<f:view> <h:dataTable var="_row" value="#{bean.rows}> <h:column> <c:choose> <c:when test="#{_row.editable}"> <h:inputText value="#{_row.value}" /> </c:when> <c:otherwise> <h:outputText value="#{_row.value}" /> </c:otherwise> </c:choose> </h:column> </h:dataTable> </f:view>
Although from the pure XML standpoint this looks valid, it is not. Thinking about what I just said it is a simple problem:
Data table component created from the data table JSP tag
Column component created from its JSP tag
The when tag in the choose attempts to evaluate #{_row.editable}
Since _row is not bound (yet) in the EL resolver, null is returned
(an argument could be made that the EL engine should throw an error or at least give a warning, but that is not how it is designed)
Since null is technically false, the outputText is created instead of the inputText
The output text component is created by its tag
So the page author was probably expecting that the choose would be evaluated for every row in the table. But the table has no rows at this point, the component is being created. So, the inputText component is never created as the when tag will not process its contents if the test fails.
The proper solution is to use JSF functionality and not JSP functionality. To the confusion of JSP developers, there are no c:if, c:choose or c:forEach equivalent components (see the Tomahawk Sandbox limitRendered for c:if and c:choose functionality and the Tomahawk dataList or Trinidad iterator components for c:forEach type of functionality). Without third party components, the rendered attribute can also work, although it requires more work:
<f:view> <h:dataTable var="_row" value="#{bean.rows}> <h:column> <h:inputText value="#{_row.value}" rendered="#{_row.editable}" /> <h:outputText value="#{_row.value}" rendered="#{not _row.editable}" /> </h:column> </h:dataTable> </f:view>
In this case both the input and the output components are created. The rendered is evaluated by the renderer during the rendering phase while the data table is iterating over each of its rows.
When it is okay to use JSP tags with JSF
So now that you know the problem, you may ask why is using any non-JSF, JSP tags allowed? This is because they still work, but must be used correctly. Since JSP tags are evaluated while components are being built, they can control which components to create. For example, I may want to include certain components in a page template if the current user is an administrator. Because the components are not created if the user is not an administrator, there will be less components objects created and less components to process for each JSF lifecycle phase, and thus improving performance.
It is very important to remember that you cannot have components "re-appear" on post back of a JSF form. This is because a JSF component tree should never be altered between having its state saved and when its state is restored. This is very important, so let me say again, a JSF component tree should never be altered between having its state saved and when its state is restored. The reason is that this would violate the JSF specification/design. Take for example a c:forEach loop that when evaluated had five items it its list. Assuming that there was one JSF component tag inside the for each tag, that means five components were created. Now JSF saves the state for five components. Then lets say this for each loop data is coming from a database that can change and now there are only four items. When JSF attempts to restore the component tree, there is data for 5 components, but there are only 4 in the component tree. This causes a restore state exception.
Therefore, always ensure that when a component tree is restored, it is not changed! There is no problem changing a component tree after restoring it or before saving it, only between those times.
Hey, what about Facelets?
I did mention that I would talk about facelets, didn't I?
Facelets is similar in its behavior to JSP although it has much more efficient code and is designed quite differently than JSP. Instead of JSP tags, facelets has TagHandlers. These tag handlers analyze the XML content of a facelet and create components. Just like JSP tags, the tag handlers have no access to the render-time scope of the components. In fact, facelets provides tag handlers to mimic the JSTL functionality. These tag handlers have the same pitfalls as the JSP tags. Therefore, the same considerations and rules apply to tag handlers that apply to JSP tags.
Other Blogs
Here are some other helpful resources on this topic:
c:foreach vs ui:repeat in facelets
另 参考 http://news.sina.com.cn/pc/2009-11-13/326/1504.html
Build time vs. render time
Overview
There always seems to be someone posting about how MyFaces or JSF is "broken" and it turns out that they misused JSTL tags. No matter how many times a solution is posted, the issue comes up again. Therefore, I am writing this blog to help those that do not understand how facelets and JSP view handlers work.
The Problem
JSF works entirely differently than JSP. JSP, when used for JSF, is used to build a JSF component tree, not render a page. JSTL tags alter the contents of what is built, the component tree, not the HTML that is output by the component renderers.
A Background of JSP
JSP was written so that authoring servlets would be easier. JSP pages are servlets, nothing more. Using a JSP compiler, a JSP file is compiled into a Java Servlet. Before tag libraries were introduced, JSP pages simply were compiled down into System.out.println(...); statements.
Tag libraries enhanced JSP by providing an API to tag authors to write Java code that would not have to be embedded in <% ... %> tags. The tags gave developers access to the text content of the tag body so that they could alter it or use it in a custom way. After some time, Sun released the Java standard tag library API, also known as the JSTL.
The JSTL
The JSTL is a set of JSP tags to perform common JSP functionality (note that they are not related to JSF in any way at all). Many of them perform logic to alter their contents. In the case of c:if and c:choose, they choose which tag contents to be included in the response or not.
I will be mainly talking about the JSTL core tags in this article (catch, choose, forEach, forTokens, if, etc.). It is these that have such a profound, and often confusing to some people, affect on JSF.
What JSF Is
JSF is a component technology, and architecturally is not related to JSP at all. In fact, using JSP with JSF has drawbacks, included serious performance implications due to the architecture of JSP and how the JSP view handler works.
Note
Sun probably made the default view handler as one that uses JSP, so they would not have to admit that JSP did not meet the needs of users and needed to be replaced.
Component Technology
What I mean by JSF being a component technology, is that HTML is produced by the processing of a component tree by renderers. This design is much more similar to Swing than it is Servlets and JSP. Regardless of the view handler that is used, a tree of components is built.
Note
A component is simply a Java Object that implements the UIComponent interface, nothing more.
These components simply store attributes, have some behaviors and are similar in nature to the Swing Tree component. JSF relies on renderers (classes that extend Renderer) to produce content from the component tree. During the restore view, a JSF view should be restored to its previous state, so that it appears to code that there was never a round trip for the code to the client (this is important as I discuss the JSTL tags and especially c:forEach).
Note
Components do not have to use renderers to produce their content, but it is considered bad design to use the encode methods in a component to render a response.
Note
JSF is typically used to produce HTML, but can be used to generate any output that doesn't even have to be XML related, although the ResponseWriter's API is designed for XML content.
JSF with JSP
JSF is implemented using JSP by default (see my note above why this stinks). What this means is that JSP is used to build the JSF component tree. This is important to note because JSP is not used to generate any of the HTML, unlike a typical JSP page. There are two main stages of JSF on JSP:
Building of the component tree using JSP tags
Rendering of the component tree using the standard JSF lifecycle
Building of the component tree using JSP tags
As I mentioned earlier, JSF is a component technology. When JSP tags are used, instead of writing text (HTML) onto the servlet response, the tags create components and set attribute values on them. Most of this work is done by UIComponentClassicTagBase. The class hierarchy is:
java.lang.Object
javax.faces.webapp.UIComponentTagBase
javax.faces.webapp.UIComponentClassicTagBase
javax.faces.webapp.UIComponentELTag
javax.faces.webapp.UIComponentTag
The doStartTag method of UIComponentClassicTagBase calls findComponent, which despite its name creates the component (if needed) and calls setProperties. Therefore, the JSF component is created when the start of the JSP tag is processed. The setProperties method is responsible for setting the attributes of the component. Typically there is a one-to-one map of JSP tag attribute to JSF component attribute, so the setProperties simply copies the attributes over, doing any necessary conversion of the string value in the JSP attribute to an object that the component expects for the attribute.
How JSTL fits in
Most of the "work" of a component takes place during rendering. For example, the h:dataTable sets up the var attribute during rendering (and other phases too, but that is not pertinent to this article). This means that EL expressions that rely on variables that only have scope during the rendering phase are not valid during component creation. That is to say, there is no component lifecycle method for when the component is created.
Since JSTL tags are plain JSP tags and do not involve the JSF lifecycle, they do not have access to the environment that components create, like the var variable of an h:dataTable. Take this code for example:
<f:view> <h:dataTable var="_row" value="#{bean.rows}> <h:column> <c:choose> <c:when test="#{_row.editable}"> <h:inputText value="#{_row.value}" /> </c:when> <c:otherwise> <h:outputText value="#{_row.value}" /> </c:otherwise> </c:choose> </h:column> </h:dataTable> </f:view>
Although from the pure XML standpoint this looks valid, it is not. Thinking about what I just said it is a simple problem:
Data table component created from the data table JSP tag
Column component created from its JSP tag
The when tag in the choose attempts to evaluate #{_row.editable}
Since _row is not bound (yet) in the EL resolver, null is returned
(an argument could be made that the EL engine should throw an error or at least give a warning, but that is not how it is designed)
Since null is technically false, the outputText is created instead of the inputText
The output text component is created by its tag
So the page author was probably expecting that the choose would be evaluated for every row in the table. But the table has no rows at this point, the component is being created. So, the inputText component is never created as the when tag will not process its contents if the test fails.
The proper solution is to use JSF functionality and not JSP functionality. To the confusion of JSP developers, there are no c:if, c:choose or c:forEach equivalent components (see the Tomahawk Sandbox limitRendered for c:if and c:choose functionality and the Tomahawk dataList or Trinidad iterator components for c:forEach type of functionality). Without third party components, the rendered attribute can also work, although it requires more work:
<f:view> <h:dataTable var="_row" value="#{bean.rows}> <h:column> <h:inputText value="#{_row.value}" rendered="#{_row.editable}" /> <h:outputText value="#{_row.value}" rendered="#{not _row.editable}" /> </h:column> </h:dataTable> </f:view>
In this case both the input and the output components are created. The rendered is evaluated by the renderer during the rendering phase while the data table is iterating over each of its rows.
When it is okay to use JSP tags with JSF
So now that you know the problem, you may ask why is using any non-JSF, JSP tags allowed? This is because they still work, but must be used correctly. Since JSP tags are evaluated while components are being built, they can control which components to create. For example, I may want to include certain components in a page template if the current user is an administrator. Because the components are not created if the user is not an administrator, there will be less components objects created and less components to process for each JSF lifecycle phase, and thus improving performance.
It is very important to remember that you cannot have components "re-appear" on post back of a JSF form. This is because a JSF component tree should never be altered between having its state saved and when its state is restored. This is very important, so let me say again, a JSF component tree should never be altered between having its state saved and when its state is restored. The reason is that this would violate the JSF specification/design. Take for example a c:forEach loop that when evaluated had five items it its list. Assuming that there was one JSF component tag inside the for each tag, that means five components were created. Now JSF saves the state for five components. Then lets say this for each loop data is coming from a database that can change and now there are only four items. When JSF attempts to restore the component tree, there is data for 5 components, but there are only 4 in the component tree. This causes a restore state exception.
Therefore, always ensure that when a component tree is restored, it is not changed! There is no problem changing a component tree after restoring it or before saving it, only between those times.
Hey, what about Facelets?
I did mention that I would talk about facelets, didn't I?
Facelets is similar in its behavior to JSP although it has much more efficient code and is designed quite differently than JSP. Instead of JSP tags, facelets has TagHandlers. These tag handlers analyze the XML content of a facelet and create components. Just like JSP tags, the tag handlers have no access to the render-time scope of the components. In fact, facelets provides tag handlers to mimic the JSTL functionality. These tag handlers have the same pitfalls as the JSP tags. Therefore, the same considerations and rules apply to tag handlers that apply to JSP tags.
Other Blogs
Here are some other helpful resources on this topic:
c:foreach vs ui:repeat in facelets
发表评论
-
c++与java内存模型& c++ vTable
2012-11-03 16:25 930参见: http://stackoverflow.com/q ... -
maven pom 指南
2012-11-03 15:56 731http://maven.apache.org/pom.htm ... -
could not discover transaction status
2012-11-01 18:08 992https://community.jboss.org/thr ... -
zz java 类初始化顺序
2012-08-17 14:42 693zz from http://ig2net.info/arch ... -
class泛型反射相关API介绍
2012-06-21 10:49 836class泛型反射相关API介绍: 1. getGeneri ... -
服务提供者框架(Service provider framework)
2012-06-14 16:55 1098服务提供者框架(Service provider framew ... -
JMS的使用
2012-05-30 16:24 9311. 何时使用MQ 如果仅仅是为了达到异步调用的目的, ... -
java EE 6 中Jsf 2.0 managedBean和CDI关系
2012-05-29 15:55 2722转自 :http://stackoverflow.com/qu ... -
maven 默认编码
2012-05-28 15:59 5395maven会使用平台的默认编码,中文系统就是GBK 如果使用 ... -
Seam的事务管理
2012-05-17 17:10 1108Seam的事务管理 Seam和jsf绑定在一起,seam将j ... -
seam与jsf的结合
2012-04-10 23:02 844Seam与JSF的结合 1. 采用org.jboss.seam ... -
maven依赖之optional
2012-04-09 15:42 856http://maven.apache.org/guides/ ... -
Visualsvn+trac 0.12 配置
2012-03-13 09:54 898主要参考了: http://www.cnblogs.com/ ... -
seam 的interceptor分析
2012-03-12 10:36 9921. componet.initialInstance()的时 ... -
zzEJB sessionBean的生命周期
2012-02-29 22:18 804【译】 Stateless Session Be ... -
关于jboss 4 的JNDIVIew 名字空间
2012-02-27 18:11 993Jboss JNDI http://do ... -
多个EJB entity jar 使用同一个 persistence.xml
2012-02-22 18:32 710可以利用 persistence.xml 的 class、ma ... -
java的ClassLoader机制
2012-02-22 16:27 838zz from :http://www.cnblogs.com ... -
关于JPA的FlushModel---Manual
2012-02-21 17:08 1680zz from : http://www.codeinstr ... -
hibernate 分页
2011-11-01 09:10 641setFirstResult 是起始数据,setMaxResu ...
相关推荐
JSF是一种用于构建Java ... 包含JSP页面的JSF应用程序也使用由为了表现UI组件和在页面上的其他对象的JSF技术而定义的标准的tag库。 Java Server Faces技术的重要开发框架 sun-ri、myfaces、icefaces、richfaces、seam
JSP(Java Server Pages)是由Sun Microsystems公司倡导、许多公司参与一起建立的一种...JSP技术有点类似ASP技术,它是在传统的网页HTML文件(*.htm,*.html)中插入Java程序段(Scriptlet)和JSP标记(tag),从而形成JSP文档
15-1 JSP Tag Library 简介 15-2 一个简单的 Tag Library 范例 15-3 Tag Handler Class 15-4 Tag Library 范例程序 第十六章 Simple Tag 与 Tag File 16-1 Simple Tag 16-3 Tag File 16-4 Tag Library Descriptor...
MyEclipse_HTML_JSP_Web_Designer_Quickstart.pdf Outline 1. Preface 2. Requirements 3. Introduction ...1. JSF and Struts Tag Library Support 7. Preview Mode 8. FAQ 9. User Feedback 1. Preface
this is a java file ,it ...like "id=\"jsp-tag-id\"",you want to get "jsp-tag-id",then you should config start charcter id=" and the end character " ,so will get the content from id="**&&&##$%%anything
在 JavaServer Faces (JSF) 2.0 中,Facelets 取代 JavaServer Pages (JSP) 成为默认的视图声明语言 (VDL)。有了 Facelets,您不需要像以前在 JSF 1.2 中那样配置视图处理器。Facelets 是一种以 JSF 为中心的视图...
3. 个人觉得freemarker 和taglib,jsf至少在使用层面上很像,但是freemarker 的macro容易写,几行代码就搞定了,taglib和jsf需要写一堆java文件和tld文件,繁琐得很 4.freemarker 不能直接调用java对象的method. 这点...
PageOffice是标准Java组件,标准JSP Tag标签方式引用,完美支持Eclipse、MyEclipse等开发工具,完美支持JSF、SSH等开发架构。 强大的Word、Excel 动态数据填充及格式控制功能。服务器端无需安装Office软件,根据...
基于MVC模式的java体系结构图,视图包括html,css,div,ajaxflash,javascript,xml,jsf,tag,控制器包括JSP,SERVLET。
GWAP2.0定位: 1、掌握一种开发方法,能够套用到任何业务上。 2、融合下一个阶段的... 4、Servlet/JSP/标准指令/标准动作/TagLib/TagFile/EL/Filter/Listener Struts框架 :JSF(标准框架JSF,第三方框架struts)
wicketstuff-jee-web(以前的 wicket.jsp) JEEWebResolver 用于通过自定义 Wicket-Tag 将 Servlet、JSP 和 JSF 内容嵌入到邪恶的 HTML 页面中。 它使用 Wicket 6.x / 7.x 进行测试。 因为 include 用于应用内容,...
javax.el Provides the API for the Unified Expression Language shared by the JSP 2.1 and JSF 1.2 technologies. javax.enterprise.deploy.model Provides Tool Vendor implementation classes. javax....
2.5.6. 对JSF 1.2支持 2.5.7. JAX-WS支持 2.6. 其他 2.6.1. 动态语言支持 2.6.2. 增强的测试支持 2.6.3. JMX 支持 2.6.4. 将Spring 应用程序上下文部署为JCA adapter 2.6.5. 计划任务 2.6.6. 对Java 5 ...
2.5.6. 对JSF 1.2支持 2.5.7. JAX-WS支持 2.6. 其他 2.6.1. 动态语言支持 2.6.2. 增强的测试支持 2.6.3. JMX 支持 2.6.4. 将Spring 应用程序上下文部署为JCA adapter 2.6.5. 计划任务 2.6.6. 对Java 5 ...
基于EJB的真实世界模型,附源代码,部分功能需JSP配合完成。 J2ME优化压缩PNG文件 4个目标文件 内容索引:JAVA源码,综合应用,J2me游戏,PNG,图形处理 这是个J2ME控制台程序,它能剔除PNG文件中的非关键数据段,...
基于EJB的真实世界模型,附源代码,部分功能需JSP配合完成。 J2ME优化压缩PNG文件 4个目标文件 内容索引:JAVA源码,综合应用,J2me游戏,PNG,图形处理 这是个J2ME控制台程序,它能剔除PNG文件中的非关键数据段,...
Google Tag Library 该标记库和 Google 有关。使用该标记库,利用 Google 为你的网站提供网站查询,并且可以直接在你的网页里面显示搜查的结果。 github-java-api github-java-api 是 Github 网站 API 的 Java 语言...
Google Tag Library 该标记库和 Google 有关。使用该标记库,利用 Google 为你的网站提供网站查询,并且可以直接在你的网页里面显示搜查的结果。 github-java-api github-java-api 是 Github 网站 API 的 Java 语言...
Google Tag Library 该标记库和 Google 有关。使用该标记库,利用 Google 为你的网站提供网站查询,并且可以直接在你的网页里面显示搜查的结果。 github-java-api github-java-api 是 Github 网站 API 的 Java 语言...