会话范围意外行为

时间:2011-08-27 08:11:48

标签: java jsf java-ee primefaces

我有一个JSF页面,用户可以将他们的汽车输入我的数据库。表单有三个输入字段:

  • 制造商
  • 模型
  • 注册

ManufacturerModel字段都是自动填充字段。为了完成Model字段,我需要知道用户在提交表单之前在Manufacturer字段中选择了什么值。为此,我设置了一个AJAX调用来通知托管bean所选的值:

<p:autoComplete id="manufacturer"
                minQueryLength="3"
                completeMethod="#{carController.complete}"
                forceSelection="true">
   <p:ajax event="itemSelect"
           listener="#{carController.manufacturerSelected}" />
</p:autoComplete>

在托管bean中:

public void manufacturerSelected(SelectEvent se) {
    manufacturer = se.getObject().toString();
}

模型的自动完成字段和处理程序方法看起来大致相同,值略有不同。

要在多个XHR请求中保留manufacturer值,我已将bean设置为ConversationScoped并以@PostConstruct带注释的方法开始对话:

@Named
@ConversationScoped
public class CarController implements Serializable {

@Inject
private Conversation conversation;

@PostConstruct
private void init() {
    conversation.begin();
}

我期望bean只为页面实例化一次,因为对话尚未结束,并保留manufacturer字段中的值。但是,这并不成立,并且对于每个XHR请求再次实例化bean,导致manufacturer字段也是null。在PostConstruct方法中设置断点显示它实际上已被调用,manufacturerSelected方法也是如此。

我怀疑这与我不是手动传播会话ID这一事实有关,但文档说这个ID应该自动传播任何面部请求。这实际上是否正确,这是否意味着XHR请求不一定面临请求?

编辑:在bean的各个位置设置断点表明每个XHR请求都有一个新的bean(conversation.getId()不断变化)所以我显然没有正确传播ID。如何使用p:ajax传播ID?我在哪里可以用EL获取它?

2 个答案:

答案 0 :(得分:1)

由于您并未真正使用对话(至少在您提供的示例中没有),为什么不使用视图范围?这将完全符合您的要求,而无需传播会话ID。

请注意,要使@ViewScoped起作用,您必须将bean更改为JSF托管bean(删除@Named)。这是由于Java EE 6中的设计错误/规范疏忽。如果您想继续使用CDI,那么可以使用Seam 3中的Java EE 6扩展来修复此错误。

答案 1 :(得分:0)

烨。这是JSF 2和Primefaces一起不传播会话ID的问题。您可以尝试以下解决方法。 (这是由于同样的问题,其他人将在这里结束)。

<p:autoComplete id="manufacturer"
            minQueryLength="3"
            completeMethod="#{carController.complete}"
            forceSelection="true" onchange="updateManufacturer([{name:'cid',value:'#{javax.enterprise.context.conversation.id}'}])">
</p:autoComplete>
<p:remoteCommand name="updateManufacturer" action="#{carController.manufacturerSelected}"
                                 process="manufacturer" />