帮助处理//request 作用域 bean 行为吗?
我正在尝试处理众所周知的“问题”,其中 ah:commandLink 的操作方法在放置在从请求作用域 bean 获取数据的 dataTable 中时不会被调用。由于项目限制,我仅限于使用 JSF 2.0 和 RichFaces 3.x(部分支持它),因此我不能依赖 Tomahawk 的解决方案(preserveDataModel)。
经过一天的搜索和试验/错误:
- 我读到数据表所依赖的“数据模型”需要存储在会话中。我怎样才能做到这一点而不使整个 bean 成为会话范围的 bean?我尝试使用保存数据的静态变量,但不起作用。
- 我尝试将 a4j:keepAlive 与我的 bean 一起使用(它实现了可序列化,如果重要的话),但未能使其工作。
- 使 bean ViewScoped 也不起作用。
任何与此相关的帮助将不胜感激。
编辑:
这就是我想要做的:
在页面中,有一个组合显示从数据库检索的许多选项。当用户选择一个时,数据表中将填充与所选选项相关的信息。第一列的数据呈现为命令链接。如果用户单击该链接,它应该调用指定的方法,但它不会被调用。
mypage.xhtml
<h:form>
<!-- Placed a <a4j:keepAlive beanName="myBean"> in this line, but didn't work -->
<h:selectOneMenu value="#{myBean.selectedOption}">
<f:selectItems value="#{myBean.optionsList}" var="option"
itemLabel="#{option.labelProperty}" itemValue="#{option.valueProperty}"/>
<a4j:support event="onchange" action="#{myBean.getDataBasedOnSelectedOption}"
reRender="table_panel" ajaxSingle="true"/>
</h:selectOneMenu>
<a4j:outputPanel id="table_panel" >
<rich:dataTable id="table" value="#{myBean.data}" var="dataRow"
rendered="#{not empty myBean.selectedOption}">
<f:facet name="header">
<rich:columnGroup>
<rich:column>Some column header</rich:column>
</rich:columnGroup>
</f:facet>
<rich:column>
<a4j:commandLink action="#{myBean.linkClickedAction}"
value="#{dataRow.someProperty}"/>
</rich:column>
</a4j:outputPanel>
MyBean.java
@ManagedBean(name="myBean")
@RequestScoped //Tried with @ViewScoped but didn't work
private List<MyPOJO1> optionsList;
private List<MyPOJO2> data; //Made this variable static, but didn't work
private String selectedOption;
@PostConstruct
public void init()
{
optionsList = getOptionsListFromDatabase();
}
public String getDataBasedOnSelectedOption()
{
data = getRelevantDataFromDatabase(selectedOption);
return null;
}
//This method doesn't get called
public String linkClickedAction()
{
System.out.println("I'm here!");
return null;
}
public List<MyPOJO1> getOptionsList()
{
return optionsList;
}
public void getSelectedOption()
{
return selectedOption;
}
public void setSelectedOption(String selectedOption)
{
this.selectedOption = selectedOption;
}
I'm trying to deal with the well known "issue" where the action method of a h:commandLink doesn't get invoked when placed inside a dataTable that gets its data from a request scoped bean. Due to project constraints, i'm limited to use JSF 2.0 and RichFaces 3.x (which partially supports it), so i can't rely on Tomahawk's solution (preserveDataModel).
After a day spent on searching and trial/error:
- I've read that the "data model" that the dataTable feeds on needs to be stored in the session. How can I do that without making the whole bean a session scoped one? I tried with a static variable that holds the data, but doesnt work.
- I've tried to use the a4j:keepAlive with my bean (that implements Serializable, if it matters), but failed to make it work.
- Making the bean ViewScoped doesn't work either.
Any help regarding to this would be appreciated.
EDIT:
Here is what i'm trying to do:
In the page there is a combo displaying a number of options retrieved from the database. When the user selects one, a dataTable is filled with info related to the option selected. The data of the first column are rendered as command links. If the user clicks the link, it should invoke the specified method, but it doesn't get called.
mypage.xhtml
<h:form>
<!-- Placed a <a4j:keepAlive beanName="myBean"> in this line, but didn't work -->
<h:selectOneMenu value="#{myBean.selectedOption}">
<f:selectItems value="#{myBean.optionsList}" var="option"
itemLabel="#{option.labelProperty}" itemValue="#{option.valueProperty}"/>
<a4j:support event="onchange" action="#{myBean.getDataBasedOnSelectedOption}"
reRender="table_panel" ajaxSingle="true"/>
</h:selectOneMenu>
<a4j:outputPanel id="table_panel" >
<rich:dataTable id="table" value="#{myBean.data}" var="dataRow"
rendered="#{not empty myBean.selectedOption}">
<f:facet name="header">
<rich:columnGroup>
<rich:column>Some column header</rich:column>
</rich:columnGroup>
</f:facet>
<rich:column>
<a4j:commandLink action="#{myBean.linkClickedAction}"
value="#{dataRow.someProperty}"/>
</rich:column>
</a4j:outputPanel>
MyBean.java
@ManagedBean(name="myBean")
@RequestScoped //Tried with @ViewScoped but didn't work
private List<MyPOJO1> optionsList;
private List<MyPOJO2> data; //Made this variable static, but didn't work
private String selectedOption;
@PostConstruct
public void init()
{
optionsList = getOptionsListFromDatabase();
}
public String getDataBasedOnSelectedOption()
{
data = getRelevantDataFromDatabase(selectedOption);
return null;
}
//This method doesn't get called
public String linkClickedAction()
{
System.out.println("I'm here!");
return null;
}
public List<MyPOJO1> getOptionsList()
{
return optionsList;
}
public void getSelectedOption()
{
return selectedOption;
}
public void setSelectedOption(String selectedOption)
{
this.selectedOption = selectedOption;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如果
a4j:keepAlive
或@ViewScoped
不起作用,那么数据模型的数据加载逻辑很可能是错误的。您可能会根据某些参数将其加载到 getter 中,而不是在 bean 的操作方法、构造函数或@PostConstruct
中进行加载。也就是说,在 JSF 生命周期的应用请求值阶段也会调用 getter 来确定按下命令链接的行,以便 JSF 可以确定需要调用哪个操作。如果 getter 没有返回包含预期行的数据模型,则不会调用该操作。相应地修复它。 getter 应该只返回 bean 属性或者最多只进行延迟加载。
If
a4j:keepAlive
or@ViewScoped
doesn't work, then the chance is big that the data loading logic for the datamodel is wrong. Likely you're loading it inside the getter based on some parameters instead of doing it in the action method, or constructor, or@PostConstruct
of the bean. The getter will namely also be called during apply request values phase of the JSF lifecycle to determine the row on which the commandlink is pressed, so that JSF can determine which action needs to be invoked. If the getter doesn't return the datamodel with the expected row, then the action simply won't be invoked.Fix it accordingly. The getter should only return the bean property or at highest only do lazy loading.