我有以下会话范围的支持bean:
@Named
@ConversationScoped
public class TestConversation implements Serializable {
private Logger logger = LoggerFactory.getLogger(TestConversation.class);
private List<Integer> numbers;
@Inject
private Conversation conversation;
@PostConstruct
public void init() {
logger.info("Creating TestConversation bean!!!");
numbers = new ArrayList<Integer>();
numbers.add(3);
numbers.add(4);
numbers.add(5);
numbers.add(6);
conversation.begin();
}
public void commandLinkAction() {
logger.info("Invoking commandLinkAction");
}
public List<Integer> getNumbers() {
return numbers;
}
}
以下小面目视图:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<title>Testing Conversation</title>
</h:head>
<h:body>
<h:form>
<h:dataTable value="#{testConversation.numbers}" var="num">
<h:column>
<h:outputText value="#{num}"/>
</h:column>
<h:column>
<h:commandLink action="#{testConversation.commandLinkAction}">Trigger form submission</h:commandLink>
</h:column>
</h:dataTable>
</h:form>
</h:body>
</html>
当我进入页面时,我看到INFO: Creating TestConversation bean!!!
这是正确的。
然后我点击h:commandLink
,我看到了:
信息:创建TestConversation bean !!!
信息:调用commandLinkAction
再次创建bean,这意味着没有传播对话。我认为这与以下内容相矛盾:
引自docs:
与呈现JSF视图的请求相关联的长时间运行的对话上下文会自动传播到源自该呈现页面的任何面部请求(JSF表单提交)。
如果我添加此<f:param name="cid" value="#{javax.enterprise.context.conversation.id}"/>
,那么一切正常。我有误会吗?
P.S没有f:param
,当我第二次点击commandLink
时,它可以正常工作,但不是第一次:(。
答案 0 :(得分:3)
我想,问题似乎是在处理<h:form>
组件时未启动会话,因此表单的操作第一次没有cid。
第二次,当您点击链接testConversation.commandLinkAction
时,访问testConversation
会使对话开始,然后再处理<h:form>
尝试以下更改
如果您在#{testConversation}
之前放置<h:form>
示例工作正常,因为在处理<h:form>
希望这会有所帮助..
答案 1 :(得分:2)
在前一个答案的基础上,肯定是因为TestConversation
bean没有被构建,直到表格自动包含cid
已经太晚了。
在这种情况下,您正在初始化视图的数据,因此最好将它放在preRenderView事件侦听器中。
<f:event type="preRenderView" listener="#{testConversation.init}"/>
尽早将其放在您的facelet模板中,例如f:metadata
(因为它经常与f:viewParam
一起使用),并删除@PostConstruct
注释。这使得init
的调用显式而不是依赖它作为正在构造的bean的副作用运行,因为它在EL表达式中被引用。