风景:
<h:form ...
<p:dataTable value="#{myBean.list}" var="data" ...
<p:column ...
<h:commandButton action="#{controller.method(data.id)}" />
</p:column>
</p:dataTable>
</h:form>
控制器:
@ApplicationScoped
public class Controller {
public String method(final Long dataId) {
/* Do business */
return URL_WITH_REDIRECT;
}
}
生产者
(使用此处@ViewScoped
描述的 CDI 注释)
@ApplicationScoped
public class Producer {
@Named @ViewScoped @Producer
public MyBean getMyBean() {
final MyBean bean = new MyBean();
bean.list = new ArrayList<Data>(); // where Data has a Long id field
/* Do business and populate list */
return bean;
}
}
问题及其场景
GET
这页纸- 豆子生产出来了
- 视图被渲染
- 响应发送到浏览器
- 点击按钮
- 数据被
POST
ed到服务器 - 阶段1-4 执行没有任何问题,并且
@ViewScoped
按预期使用 bean - 阶段 5:
controller.method
调用data.id
并访问1.1生成的 bean - 方法返回重定向
String
- !!制作人又来电了!!- 我们仍处于 APPLICATION_INVOCATION 阶段,但在实际方法调用之后
- 数据被
- 浏览器接收重定向
GET
下一页 ...
有效的半“驴”解决方案:
简而言之:点击时,将 id 复制到数据表之外,然后触发点击提交按钮。
在h:commandButton
表格列的内部添加:
onclick="$('input[id*=selectedDataId]').val('#{data.id}'); $('button[id*=callMethod]').trigger('click');"
表外:
<h:inputHidden id="{selectedDataId}"binding="#{selectedDataId}"/>
<p:commandButton type="submit"
id="callMethod"
label="Hidden button"
action="#{controller.method(selectedDataId.value)}"/>
最后它可以工作,但我无法弄清楚是什么原因导致第一种和基本方法重新初始化视图范围 bean。查看堆栈跟踪(见下文)似乎正在重建行。
问题:
有没有人对此问题有解释,也许还有一些注意事项?
堆栈跟踪
其中:getPipelinecheckSearchResults
是用于检索支持表的列表的调用,这会导致调用生产者
我已经浏览过的内容:
我已经阅读了以下文章/SO问题,但没有更好地理解上述(第一个)解决方案为何如此有效。
每次单击 dataTable 中的 commandButton 时,都会重新创建 ViewScoped bean
为什么 @PostConstruct 回调每次都会触发,即使 bean 是 @ViewScoped 的?JSF
如何将选定的行传递给 dataTable 中的 commandLink?
http://balusc.blogspot.de/2010/06/benefits-and-pitfalls-of-viewscoped.html