1

さて、私は ConversationScoped を使用しています。PostConstruct が会話の開始時に 1 回だけ呼び出されることを願っています。以下を参照してください。

@Named("disciplinaDetalheMB")
@ConversationScoped
public class DisciplinaDetalheMBImpl {

    private static final long serialVersionUID = 1L;

    @Inject
        private Conversation conversation;

    @Inject
    @AnBasicBO
    private BasicBO boPadrao;

@PostConstruct
    public void postConstruct() {
    logger.debug("Iniciando PostConstruct...");
    init();
    beginConversation();
    }

public String salvarAndRedirecionar() {
    salvar();
    if (!FacesContext.getCurrentInstance().isValidationFailed()) {
        return goToLastPage() + "?faces-redirect=true";
    } else {
        return "";
    }
    }


private void beginConversation() {
    if (!conversation.isTransient()) {
        endConversation();
    }
    conversation.begin();
    if (conversation.isTransient()) {
        throw new RuntimeException("A conversão não foi iniciada corretamente");
    }
    SessionContext.getInstance().setAttribute("cid", conversation.getId());

    }

    public BasicBO getBoPadrao() {
        return boPadrao;
    }

    public void setBoPadrao(BasicBO boPadrao) {
        this.boPadrao = boPadrao;
    }

}

したがって、バッキング Bean が作成されると、会話が初期化され、CID がセッションに保存されてから使用されます。XHTML に commandButton の「保存」があり、このボタンが呼び出されると、PostConstruct が再度呼び出されます。理由はわかりません。

<h:commandLink
            action="#{managedBeanName.salvarAndRedirecionar()}"
            styleClass="btn btn-info pull-right" value="Salvar">
            <f:ajax execute="@form" />
        </h:commandLink>

生成された HTML は次のとおりです。

<a id="formManterDisciplina:j_idt44:j_idt46" href="#" onclick="mojarra.ab(this,event,'action','@form',0);return false" class="btn btn-info pull-right" name="formManterDisciplina:j_idt44:j_idt46">Salvar</a>

したがって、「href=#」がオンリックの実行を回避することは理解しています。これが問題だと思いますが、修正方法がわかりません。注意: postConstruct は常に前に呼び出されるため、salvarAndRedirecionar() メソッドは呼び出されません。

2) 別の質問があります: 会話を始めても終わらない場合は、何か問題がありますか? 会話を手動で終了したくない場合があります。これは、ページが 1 つしかないためです。開始するだけです。

4

1 に答える 1

4

この問題が発生する理由は、会話スコープ Bean の postconstruct メソッドで会話開始メソッドを呼び出しているためです。そのため、会話は、応答のレンダリング フェーズの前ではなく、その間に長時間実行状態に設定されます。問題は、CID パラメーターが HTML フォーム要素でレンダリングされることですが、この時点では会話はまだ一時的な状態です。これは、リクエスト後に postconstruct メソッドがまだ呼び出されていないためです。commandLink 要素を再定義するときに postconstruct メソッドが呼び出されますが、それでは遅すぎて、HTML フォーム要素に CID パラメータが含まれません。

<form id="yourForm" name="yourForm" method="post" action="/path/to/yourPage.xhtml" enctype="application/x-www-form-urlencoded">

したがって、解決策は、会話の開始点を応答のレンダリング フェーズの前に移動することです。f:viewActionJSF 2.2 を使用している場合はタグf:eventを使用し、古いバージョンを使用している場合は タグを使用して実行できます。

そして、次のように、HTML フォーム要素内にレンダリングされた CID パラメータが表示されます。

<form id="yourForm" name="yourForm" method="post" action="/path/to/yourPage.xhtml?cid=1" enctype="application/x-www-form-urlencoded">

  • f:eventタグを使用する場合:

あなたのページで:

<f:metadata>
    <f:event listener="#{disciplinaDetalheMB.initConversation}" type="preRenderView" /> 
</f:metadata>

バッキング Bean で:

public void initConversation(){
    if (!FacesContext.getCurrentInstance().isPostback() && conversation.isTransient()) {
          conversation.begin();
    }
}
  • f:viewActionタグを使用する場合:

あなたのページで:

<f:metadata>
    <f:viewAction action="#{disciplinaDetalheMB.initConversation}" />
</f:metadata>

バッキング Bean で:

public void initConversation(){
    if (conversation.isTransient()) {
          conversation.begin();
    }
}

2 番目の質問については、HTTP セッションのようなタイムアウトがあるため、会話を終了しないことに大きな問題はありません。サーバー リソース管理戦略とアイドル状態の会話に必要な有効期間に応じて、タイムアウト値を設定できます。とにかく、ページが 1 つしかない場合は、ビュー スコープのバッキング Bean を使用することをお勧めします。

于 2015-10-19T21:31:23.153 に答える