原文:http://blogs.sun.com/rlubke/entry/jsf_2_0_new_feature2
请注意: 这是由 JSF中文技术文摘 <http://hi.baidu.com/jsfcn>翻译的文章,如有出入之处,请参考原文连接.如需转载请保留该段信息.
这是关于介绍JSF 2.0新功能提议草案系列博客中的第一篇介绍. 请记住 所描述的任何功能都不是最终草案,并且可能会被修订, 但是这是个展示这些新特性(现在已有的和即将加入的)的一个好机会.
我们即将开始发布Mojarra 2.0 <https://javaserverfaces.dev.java.net/>的Nightly Builds 到该项目站点中,但是在准备期间,你不得不自己签出<http://wiki.glassfish.java.net/Wiki.jsp?page=JavaServerFacesRI#section-JavaServerFacesRI-HowDoIAccessTheSourceTreeViaCVS>
这些代码并且建构<http://wiki.glassfish.java.net/Wiki.jsp?page=JavaServerFacesRI#section-JavaServerFacesRI-HowDoIBuildTheMojarra>它们(幸运的是 建构是很容易的).
那么,什么是ProjectStage 特性呢? 简单的说, JSF 2.0 EG 同意ROR 的 RAILS_ENV<http://wiki.rubyonrails.org/rails/pages/Environments> 特性. javax.faces.application.ProjectStage 提供如下的选项:
* Production
* Development
* UnitTest
* SystemTest
* Extension
这些值通过Context init-parameter来配置,例如: <context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
在运行时,你可以查询Application 对象,通过调用Application.getProjectStage() 函数来得到配置的值. 返回值是定义的Enum中的一个.如果没有指定该值,默认值为 Production. 除了Extension外,其他的值都是自解释的,那么 Extension是用来干什么的? 该选项允许开发者使用自定义Stage. 因此如果一个指定的值不和任何一个预定义的Enum值匹配,那么该值就用作自定义Stage.
当调用Application.getProjectStage() 时候,将返回这个Extension enum值. 在返回的值上调用toString() 函数,将返回在web.xml中配置的值. {So if
a value is specified that doesn't match the existing enumerate values, then
it will be the value for used. When calling Application.getProjectStage() the
Extension enum value will be returned. Calling toString() on the return values
at this point will return the value as configured in the web.xml.} 在对于在JSF框架上添加新的Stage的开发者来说是很有用的,新加的Stage来实现预定义类型以外的其他功能. 这里的总体思路是,通过这些值可以影响到JSF的行为. 举个例子来说明下: 一个简单的JSF View,包含几个通过验证的输入域和没有通过的. 如果在View上没有h:messages组件, 这个页面看上去没有做任何事情(译者注:如果添加了h:messages组件,将会有错误提示信息).
我不能告诉你我在论坛上遇到过多少次这种问题了, 并且第一个回帖总是 "Add h:messages to your view and try again(在你的View中添加h:messages 然后再测试下)". 这里是ProjectStage解决的办法: 如果当前的Stage为 Development 并且在View中没有h:messages标签, 我们将为用户自动添加一个. 如果Stage是Production,我们将不会做任何动作(假设用户做的都正确,没有必要修改组件树了). 尽管该特性看起来相当的微小,但是我想首先讨论它, 应为它对我在下一篇文章中讲到的特性很关键 -- - stay tuned.
UPDATE: 2/19/2008 - JNDI configuration implemented (译者注: 作者根据博客的评论 做的更新)
根据该博客的评论,我们实现了通过JNDI来配置ProjectStage的功能. Application.getProjectStage()第一次调用的时候,它将先从JNDI上检查该值, 如果没有发现,然后才从Context init parameter中查找, 最后如果没有值就使用默认值 ProjectStage.Production.
当前该JNDI名字为: java:comp/env/jsf/ProjectStage. 另外,我们也添加了一个JNDI ObjectFactory 来使开发者很容易的从全局资源中配置ProjectStage. 下面是一个如何在Glassfish中定义ObjectFactory的示例: pic. 属性stage的值将从JNDI lookup中返回. 应该注意: 很不幸的是 映射全局JNDI资源到组件资源(java:comp/env)作为启动项来实现(an implementation specific process). 所以要使用Glassfish来示例, 你必须在web.xml中添加一个resource-ref 节点. <resource-ref>
<res-ref-name>jsf/ProjectStage</res-ref-name>
<res-type>java.lang.String</res-type>
</resource-ref>
然后,你需要通过sun-web.xml文件(在/WEB-INF/中)来映射res-ref-name到 全局JNDI资源中去.
<resource-ref>
<res-ref-name>jsf/ProjectStage</res-ref-name>
<jndi-name>javax.faces.PROJECT_STAGE</jndi-name>
</resource-ref>
另外一种选择, 你可以在web.xml中配置一个JNDI,通过一个简单的env-entry来实现. 但是这样你必须修改web.xml文件才能配置所有程序的ProjectStage.