我有一个JSF facelets页面,根据他们正在查看的页面显示数据表.当我显示第1页时,我调用view()
action方法从数据库获取两个页面的数据,并将其存储为bean的私有成员字段(两个数组).我还调用conversation.start()
了view()
方法中注入的会话实例.
当用户单击"下一步"按钮(h:commandButton
)转到第2页时,我正在执行一个next()
方法来更新支持bean以指向数组2,以便打印出其内容.问题是,阵列2不再存在.我不知道为什么我会失去对话范围.有任何想法吗?
//tells the object which page we are on, and thus what data to display.
private int part = 1;
// These arrays are filled with data but conversation scope doesn't
// keep them on the next postback.
private int[] part1 = new int[15], part2 = new int[15];
Run Code Online (Sandbox Code Playgroud) 我在浏览jsf项目中的页面时遇到BusyConversationException.如果用户在ajax调用期间尝试导航到另一个页面,则通常会发生这种情况.当用户在单击另一个链接后立即单击链接而不等待加载页面时,也会发生这种情况.
例如,如果用户点击通过类似于下面的代码生成的多个链接,我们肯定会得到此异常.另一个例子是,假设用户在文本字段上输入查询,我们的应用程序进行ajax调用以搜索此查询.在该查询期间,如果用户单击某个按钮以导航到另一个页面,则也会发生BusyConversationException.
<h:commandLink value="#{theProfile.profileName}"
title="#{theProfile.profileName}"
action="#{profileBean.aProfileSelected}">
<f:setPropertyActionListener target="#{currentProfileWebBean.theProfile}" value="#{theProfile}"/>
</h:commandLink>
Run Code Online (Sandbox Code Playgroud)
我能赶上在一个延伸ExceptionHandlerWrapper类中的ExceptionHandler类这种类型的异常,但我不能挽救我目前的状态,我可以为这种情况下做的最好的是,当这个例外发生时重定向到主页.
有没有解决方案来避免这种情况?提前感谢您的回答和评论.
在JSF 2.0中,视图范围最明显的用例是具有可能多个AJAX回发的单个页面.使用CDI而不是JSF托管bean留给我们不认为范围,使我们要么留下来实现我们自己的,使用(可能充满错误的)第三方实施或使用会话范围.
我的问题:在典型的AJAX情况下,会话范围是否值得替代视图范围?与视图范围一样,它是否允许每个会话多个实例?有什么陷阱?
我知道的陷阱之一,即当用户导航离开页面的谈话范围不会自动删除,而是超时之后被删除.但我不确定当用户在对话超时之前导航回该页面时会发生什么.
UPDATE
会话范围确实支持每个会话多个实例.这本书说明了这一点,我能够使用ch中的代码来证实这一点.2.
我有一个会话范围的 bean ComponenteM,它被注入到请求范围的 bean ComponenteC 中。
@Named
@RequestScoped
public class ComponenteC implements Serializable {
@Inject
ComponenteM componenteM;
}
Run Code Online (Sandbox Code Playgroud)
ComponenteC 有一个由 HtmlCommandLink(以编程方式创建)调用的导出方法。导出方法调用与 SAP BO 网络服务集成的网络服务,以便将报表导出到 excel。但是,只有当调用时间过长时,我才会收到 BusyConversationException。任何其他少于 10 分钟的导出都是成功的。
同时我在对话中没有其他电话(AJAX 或非 AJAX 调用)。我已经尝试在开始对话时为对话 bean 设置显式超时,但我读到它仅用作对 CDI 容器的建议,并且可能会被忽略:
public void beginConversation() {
if (conversation.isTransient()) {
conversation.setTimeout(60 * 60 * 1000);
conversation.begin();
}
}
Run Code Online (Sandbox Code Playgroud)
错误是:
ServletException.org.jboss.weld.context.BusyConversationException 的根本原因:WELD-000322 对话锁定超时:1
我还尝试通过线程发出导出请求,然后将导出的文档返回到对话中。我的想法是让一个线程忙于处理文档和 componenteC 的导出,在等待线程完成时,偶尔会检查执行 componenteM.beginConversation();
我试图理解为什么即使没有并发请求也会抛出 BusyConversationException。
谢谢你。
来自Weld CDI文档:
会话上下文自动传播任何JSF面部请求(JSF表单提交)或重定向.它不会自动传播非面部请求,例如,通过链接导航.
我想知道,跨越JSF的上下文传播是否也要求进行瞬态对话?更一般地说,是否存在关于瞬态和长期对话之间传播的差异的概述?
假设第一个问题的答案为"是",您是否可以提供需要长时间对话的用例?
我正在尝试实现Twitter登录过程.在登录过程中,用户需要被重定向到Twitter网站以输入他/她的凭证,然后他/她将被重定向到我的网站URL.在第一次重定向之前,应该在请求之间存储和保留RequestToken对象(Twitter4J库)的实例.
为此,我决定使用ConverstaionScoped bean,但遗憾的是,请求之间不保留引用的值.
这是我的JSF页面:
twitter.xhtml:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
>
<f:event listener="#{twitterLoginPageController.login()}" type="preRenderView" />
</html>
Run Code Online (Sandbox Code Playgroud)
twitterRedirect.xhtml:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
>
<f:event listener="#{twitterLoginPageController.onRedirect(param.oauth_token, param.oauth_verifier)}" type="preRenderView" />
</html>
Run Code Online (Sandbox Code Playgroud)
我的Twitter登录控制器:
@Named
@ConversationScoped
public class TwitterLoginPageController implements Serializable {
@Inject
private Conversation conversation;
// These objects should be retained between requests
Twitter twitter;
RequestToken requestToken;
public void login() {
try {
twitter = new TwitterFactory().getInstance();
requestToken = twitter.getOAuthRequestToken("...");
conversation.begin();
conversation.setTimeout(30000);
// Navigate to Twitter here
} catch (TwitterException ex) {
...
}
} …
Run Code Online (Sandbox Code Playgroud)