h:两次调用只调用一次commandButton动作

时间:2011-05-24 10:16:30

标签: java jsf action

我在我的网络应用程序上使用JSF 1.2。在我的页面test.xhtml中,我有一个包含commandButton的表单:

<h:form>
  <h:commandButton action="#{myBean.myMethod}" value="Call my method" />
</h:form>

在java源码中,我的bean就是这样:

public class MyBean {
  public void myMethod() {
    System.out.println("my method called");
  }
}

当我显示我的页面test.xhtml时,第一次单击我的命令按钮时,该动作被很好地调用。页面刷新。然后,我尝试单击命令按钮,不会调用该操作。就好像JSF生命周期直接进入RENDER_RESPONSE阶段而不调用INVOKE_APPLICATION阶段。

刷新页面,然后单击时,可以很好地调用该操作。因此,该动作在两次上被调用一次。

为了尝试理解,我非常简单地添加了一个阶段监听器:

public class MyPhaseListener implements PhaseListener{

public PhaseId getPhaseId() {
    return PhaseId.ANY_PHASE;
}

public void beforePhase(PhaseEvent event) {
    System.out.println("START PHASE " + event.getPhaseId());
}

public void afterPhase(PhaseEvent event) {
    System.out.println("END PHASE " + event.getPhaseId());
}}

当我运行测试时点击我的页面,我有以下输出:

START PHASE RESTORE_VIEW 1
END PHASE RESTORE_VIEW 1
START PHASE APPLY_REQUEST_VALUES 2
END PHASE APPLY_REQUEST_VALUES 2
START PHASE PROCESS_VALIDATIONS 3
END PHASE PROCESS_VALIDATIONS 3
START PHASE UPDATE_MODEL_VALUES 4
END PHASE UPDATE_MODEL_VALUES 4
START PHASE INVOKE_APPLICATION 5
my method called
END PHASE INVOKE_APPLICATION 5
START PHASE RENDER_RESPONSE 6
END PHASE RENDER_RESPONSE 6

START PHASE RESTORE_VIEW 1
END PHASE RESTORE_VIEW 1
START PHASE RENDER_RESPONSE 6
END PHASE RENDER_RESPONSE 6

START PHASE RESTORE_VIEW 1
END PHASE RESTORE_VIEW 1
START PHASE APPLY_REQUEST_VALUES 2
END PHASE APPLY_REQUEST_VALUES 2
START PHASE PROCESS_VALIDATIONS 3
END PHASE PROCESS_VALIDATIONS 3
START PHASE UPDATE_MODEL_VALUES 4
END PHASE UPDATE_MODEL_VALUES 4
START PHASE INVOKE_APPLICATION 5
my method called
END PHASE INVOKE_APPLICATION 5
START PHASE RENDER_RESPONSE 6
END PHASE RENDER_RESPONSE 6

START PHASE RESTORE_VIEW 1
END PHASE RESTORE_VIEW 1
START PHASE RENDER_RESPONSE 6
END PHASE RENDER_RESPONSE 6

通过使用PhaseListener,我清楚地看到,在每次生命周期的第二次调用中,RESTORE_VIEW阶段直接进入RENDER_RESPONSE而不需要我在生命周期中的操作。

有人会想并避免这种情况并且每次都为该页面执行生命周期吗?或者是每次单击命令按钮时执行操作的解决方案?

就像你告诉我的那样,我在打印件上添加了一些调试信息,比如UIViewRoot对象和会话ID。行动顺序现在提供以下信息:

START PHASE RESTORE_VIEW 1
UIViewRoot :null
Session ID : 8385AC329B4C75AB4FBCA2CE1FBDFDC7
END PHASE RESTORE_VIEW 1
UIViewRoot :javax.faces.component.UIViewRoot@7cbcb4
Session ID : 8385AC329B4C75AB4FBCA2CE1FBDFDC7
START PHASE APPLY_REQUEST_VALUES 2
UIViewRoot :javax.faces.component.UIViewRoot@7cbcb4
Session ID : 8385AC329B4C75AB4FBCA2CE1FBDFDC7
END PHASE APPLY_REQUEST_VALUES 2
UIViewRoot :javax.faces.component.UIViewRoot@7cbcb4
Session ID : 8385AC329B4C75AB4FBCA2CE1FBDFDC7
START PHASE PROCESS_VALIDATIONS 3
UIViewRoot :javax.faces.component.UIViewRoot@7cbcb4
Session ID : 8385AC329B4C75AB4FBCA2CE1FBDFDC7
END PHASE PROCESS_VALIDATIONS 3
UIViewRoot :javax.faces.component.UIViewRoot@7cbcb4
Session ID : 8385AC329B4C75AB4FBCA2CE1FBDFDC7
START PHASE UPDATE_MODEL_VALUES 4
UIViewRoot :javax.faces.component.UIViewRoot@7cbcb4
Session ID : 8385AC329B4C75AB4FBCA2CE1FBDFDC7
END PHASE UPDATE_MODEL_VALUES 4
UIViewRoot :javax.faces.component.UIViewRoot@7cbcb4
Session ID : 8385AC329B4C75AB4FBCA2CE1FBDFDC7
START PHASE INVOKE_APPLICATION 5
UIViewRoot :javax.faces.component.UIViewRoot@7cbcb4
Session ID : 8385AC329B4C75AB4FBCA2CE1FBDFDC7
my method called
END PHASE INVOKE_APPLICATION 5
UIViewRoot :javax.faces.component.UIViewRoot@7cbcb4
Session ID : 8385AC329B4C75AB4FBCA2CE1FBDFDC7
START PHASE RENDER_RESPONSE 6
UIViewRoot :javax.faces.component.UIViewRoot@7cbcb4
Session ID : 8385AC329B4C75AB4FBCA2CE1FBDFDC7
END PHASE RENDER_RESPONSE 6
UIViewRoot :javax.faces.component.UIViewRoot@7cbcb4
Session ID : 8385AC329B4C75AB4FBCA2CE1FBDFDC7


START PHASE RESTORE_VIEW 1
UIViewRoot :null
Session ID : 8385AC329B4C75AB4FBCA2CE1FBDFDC7
END PHASE RESTORE_VIEW 1
UIViewRoot :javax.faces.component.UIViewRoot@7cbaea
Session ID : 8385AC329B4C75AB4FBCA2CE1FBDFDC7
START PHASE RENDER_RESPONSE 6
UIViewRoot :javax.faces.component.UIViewRoot@7cbaea
Session ID : 8385AC329B4C75AB4FBCA2CE1FBDFDC7
END PHASE RENDER_RESPONSE 6
UIViewRoot :javax.faces.component.UIViewRoot@7cbaea
Session ID : 8385AC329B4C75AB4FBCA2CE1FBDFDC7


START PHASE RESTORE_VIEW 1
UIViewRoot :null
Session ID : 8385AC329B4C75AB4FBCA2CE1FBDFDC7
END PHASE RESTORE_VIEW 1
UIViewRoot :javax.faces.component.UIViewRoot@7ccfa1
Session ID : 8385AC329B4C75AB4FBCA2CE1FBDFDC7
START PHASE APPLY_REQUEST_VALUES 2
UIViewRoot :javax.faces.component.UIViewRoot@7ccfa1
Session ID : 8385AC329B4C75AB4FBCA2CE1FBDFDC7
END PHASE APPLY_REQUEST_VALUES 2
UIViewRoot :javax.faces.component.UIViewRoot@7ccfa1
Session ID : 8385AC329B4C75AB4FBCA2CE1FBDFDC7
START PHASE PROCESS_VALIDATIONS 3
UIViewRoot :javax.faces.component.UIViewRoot@7ccfa1
Session ID : 8385AC329B4C75AB4FBCA2CE1FBDFDC7
END PHASE PROCESS_VALIDATIONS 3
UIViewRoot :javax.faces.component.UIViewRoot@7ccfa1
Session ID : 8385AC329B4C75AB4FBCA2CE1FBDFDC7
START PHASE UPDATE_MODEL_VALUES 4
UIViewRoot :javax.faces.component.UIViewRoot@7ccfa1
Session ID : 8385AC329B4C75AB4FBCA2CE1FBDFDC7
END PHASE UPDATE_MODEL_VALUES 4
UIViewRoot :javax.faces.component.UIViewRoot@7ccfa1
Session ID : 8385AC329B4C75AB4FBCA2CE1FBDFDC7
START PHASE INVOKE_APPLICATION 5
UIViewRoot :javax.faces.component.UIViewRoot@7ccfa1
Session ID : 8385AC329B4C75AB4FBCA2CE1FBDFDC7
my method called
END PHASE INVOKE_APPLICATION 5
UIViewRoot :javax.faces.component.UIViewRoot@7ccfa1
Session ID : 8385AC329B4C75AB4FBCA2CE1FBDFDC7
START PHASE RENDER_RESPONSE 6
UIViewRoot :javax.faces.component.UIViewRoot@7ccfa1
Session ID : 8385AC329B4C75AB4FBCA2CE1FBDFDC7
END PHASE RENDER_RESPONSE 6
UIViewRoot :javax.faces.component.UIViewRoot@7ccfa1
Session ID : 8385AC329B4C75AB4FBCA2CE1FBDFDC7


START PHASE RESTORE_VIEW 1
UIViewRoot :null
Session ID : 8385AC329B4C75AB4FBCA2CE1FBDFDC7
END PHASE RESTORE_VIEW 1
UIViewRoot :javax.faces.component.UIViewRoot@7cac2f
Session ID : 8385AC329B4C75AB4FBCA2CE1FBDFDC7
START PHASE RENDER_RESPONSE 6
UIViewRoot :javax.faces.component.UIViewRoot@7cac2f
Session ID : 8385AC329B4C75AB4FBCA2CE1FBDFDC7
END PHASE RENDER_RESPONSE 6
UIViewRoot :javax.faces.component.UIViewRoot@7cac2f
Session ID : 8385AC329B4C75AB4FBCA2CE1FBDFDC7

每个呼叫序列之间的会话始终相同。所以,我不认为这是UIViewRoot的问题。我还可以采取其他措施来测试这个问题吗?

西尔。

1 个答案:

答案 0 :(得分:1)

如果您还没有阅读此博客文章,则应该:http://balusc.blogspot.com/2006/09/debug-jsf-lifecycle.html

看起来您正在丢失会话,因为UIViewRoot不存在,因此没有UIViewRoot可以恢复。

相关问题