これはタイミングの問題のようです。preRenderView
このリスナー メソッドは、イベント中に呼び出されます。ELFlash
(によって返される Mojarra のFlash
実装)のソース コードによると、ExternalContext#getFlash()
現在レンダリング レスポンス フェーズにあり、現在のリクエストに対してまだフラッシュ Cookie が設定されていない場合、フラッシュ Cookie が設定されないことがわかります。 :
からの関連行は次のELFlash
とおりです。
if (currentPhase.getOrdinal() < PhaseId.RENDER_RESPONSE.getOrdinal()) {
flashInfo = flashManager.getPreviousRequestFlashInfo();
} else {
flashInfo = flashManager.getNextRequestFlashInfo(this, true);
maybeWriteCookie(context, flashManager);
}
はmaybeWriteCookie
、Flash Cookie を 2 回目に渡す必要がある場合 (つまり、リダイレクトされたページが別のページにリダイレクトされる場合) にのみ Cookie を設定します。
これは残念なコーナーケースです。このELFlash
ロジックは理にかなっていますが、これは実際に必要なものではありません。基本的INVOKE_APPLICATION
に、代わりにフェーズ中にメッセージを追加する必要があります。ただし、 のようなイベントはありませんpostInvokeAction
。新しい JSF 2.2<f:viewAction>
タグを使用すると、アプリケーションの呼び出し段階で実際に実行されるため、可能になるはずです。
<f:viewAction action="#{bean.onload}" />
まだ JSF 2.2 を使用していない限り、別の方法を探す必要があります。最も簡単な方法は、カスタム を作成することComponentSystemEvent
です。
@NamedEvent(shortName="postInvokeAction")
public class PostInvokeActionEvent extends ComponentSystemEvent {
public PostInvokeActionEvent(UIComponent component) {
super(component);
}
}
ここで、このイベントを公開するためのフックが必要です。最も賢明な場所は、のPhaseListener
フェーズの後のリスニングですINVOKE_APPLICATION
。
public class PostInvokeActionListener implements PhaseListener {
@Override
public PhaseId getPhaseId() {
return PhaseId.INVOKE_APPLICATION;
}
@Override
public void beforePhase(PhaseEvent event) {
// NOOP.
}
@Override
public void afterPhase(PhaseEvent event) {
FacesContext context = FacesContext.getCurrentInstance();
context.getApplication().publishEvent(context, PostInvokeActionEvent.class, context.getViewRoot());
}
}
に以下のように登録するとfaces-config.xml
<lifecycle>
<phase-listener>com.example.PostInvokeActionListener</phase-listener>
</lifecycle>
その後、次のように新しいイベントを使用できます
<f:event type="postInvokeAction" listener="#{bean.onload}" />
これを更新すると、JSF ユーティリティ ライブラリOmniFacesでも利用できるため、自作する必要はありません。InvokeActionEventListener
ショーケースの例も参照してください。