从JSF提交时,数据表中的CDI bean列表为null
请注意:这个问题是关于CDI范围的,因为我们在应用程序中使用的是CDI范围,而不是JSF范围.
Please note: This question is about CDI scopes as we are using CDI scopes in the app and not JSF scopes.
1)当我们首次访问此页面时,位于RequestScoped(企业上下文)中的Controller Bean(TestController.java)被称为index_cut.xhtml.
1) Controller Bean (TestController.java) which is in RequestScoped (enterprise context) is called index_cut.xhtml, when we come for first time on this page.
2)在加载"按钮上,我们加载以下方法来填充sapFinancialPeriodList,该方法可以正常工作并显示数据
2) On button "Load", we load the following method to populate the sapFinancialPeriodList which works fine and displays the data
>
>
>
3)更改页面上的内容并提交后,sapFinancialPeriodList
在以下方法中显示为NULL –
3) After changing the content on the page and submitting, the sapFinancialPeriodList
appears as NULL in the following method –
>
>
有什么建议吗?
您的bean受请求范围限制,并且您仅在操作时而不是在(post)构造时加载数据模型.当加载数据的操作后的HTTP响应完成时,将对Bean进行垃圾处理.后续请求将获得一个Bean的全新实例,其所有属性均设置为default.但是,由于在(后)构造期间未保留相同的数据模型,因此它保持为空.
Your bean is request scoped and you're loading the data model on action only instead of on (post)construction. When the HTTP response after the action which loaded the data is finished, then the bean is garbaged. The subsequent request would get a brand new instance of the bean with all properties set to default. However, as the same data model isn't been preserved during (post)construct, it remains empty.
在JSF2中,您可以使用@ViewScoped
解决此问题.这样,只要您通过回发(返回null
或void
)与同一个视图进行交互,该Bean就会一直存在.
In JSF2 you'd solve this with using @ViewScoped
. This way the bean will live as long as you're interacting with the same view by postbacks (which return null
or void
).
在CDI中,您需要使用@ConversationScoped
解决此问题,而这又需要一些其他@Inject Conversation
样板,并在适当的时候完成begin()
和end()
调用.有关具体示例,另请参见在JSF 2.0中用于向导模式的范围是什么?.
In CDI you'd need to solve this using @ConversationScoped
, which in turn requires some additional @Inject Conversation
boilerplate, complete with begin()
and end()
calls at the right moments. For a concrete example, see also What scope to use in JSF 2.0 for Wizard pattern?.
另一种方法是通过命令链接/按钮中的<f:param>
将负责创建数据模型的参数传递给后续请求,如下所示
An alternative is to pass the parameters responsible for creating the data model to the subsequent request via <f:param>
in the command link/button as follows
<h:commandButton value="save" ...>
<f:param name="period" value="#{bean.period}" />
</h:commandButton>
,然后在请求作用域的bean的(后)构造函数中重新创建完全相同的数据模型,如下所示:
and then recreate exactly the same data model in (post)constructor of the request scoped bean as follows
String period = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("period");
List<SapFinancialPeriod> sapFinancialPeriodList = someservice.list(period);
(如果您使用的是标准JSF,上面的方法可以更好地用@ManagedProperty
解决;据我所知,CDI没有注释,该注释使您可以将HTTP请求参数设置为bean属性)
(the above is by the way nicer to solve with @ManagedProperty
if you were using standard JSF; as far as I know CDI doesn't have an annotation which enables you to set a HTTP request parameter as a bean property)
与具体问题无关,即将到来的JSF 2.2使用新的功能带有新的@FlowScoped
注释和新的xmlns:j="http://java.sun.com/jsf/flow"
标记.
Unrelated to the concrete problem, the upcoming JSF 2.2 solves this functional requirement in a nicer way using the new "Faces Flow" feature with the new @FlowScoped
annotation and the new xmlns:j="http://java.sun.com/jsf/flow"
tags.