3

WebLogic 10.3.2 (11g)、Seam 2.2.0.GA で 2 ページしかない非常に単純なアプリケーションがあります。それぞれにコマンド ボタンがあり、他のボタンへのリダイレクト後ポストを行います。アドレスバーに表示されている現在のページの URL が表示されるため、これはうまく機能します。

しかし、私は長時間の会話を定義していませんが、ランダムな数のクリックの後、そして - 私が思うに - ランダムな秒数 (~10 秒 - 60 秒) の後、私はこの記事の最後に素敵な例外を受け取ります.

ここで、リダイレクト時に一時的な会話がどのように機能するかを理解していれば、次のことが起こります。

  1. アプリケーションを初めて見たとき、URL はhttp://localhost:7001/myapp です。
  2. pageA.xhtml のボタンをクリックすると、「pageB.xhtml?cid=26」になります。Seam は最初のリクエストの一時的な対話をリダイレクトの renderResponse フェーズまで持続するように拡張するため、これは正常です。そのため、拡張された一時会話の cid (会話 ID) を使用して、伝達されたパラメーターを見つけます。

  3. pageB.xhtml のボタンをクリックすると、pageA.xhtml?cid=26 になります。

同じ cid が新しい拡張一時会話に与えられました。これは、前回のリダイレクト後ポストの最後で会話が終了したため正常であり、26 番は cid として自由に使用できるわけではありません。

これはすべて正しいですか?はいの場合、なぜこのようなことが起こるのでしょうか: アプリケーションのホーム アドレス (pageA を表示) を再入力して再度クリックすると、26 とは異なる番号である pageB.xhtml?cid=29 になります。しかし、26 は終了しています。前の RenderResponse フェーズの後、URL を再入力します。29 の代わりに使用されないのはなぜですか?

それで、補足するために、2つの質問:

  1. 長時間の会話を開始していないにもかかわらず、例外が発生するのはなぜですか?
  2. シドで正確に何が起こりますか?何を基準に変わるの?

乾杯、

アップデート:

追加情報: ページ A では、次のように h:commandButtons を使用します。

<h:commandButton action="showPageB" value="Show page B" />

そしてページBで

<h:commandButton action="showPageA" value="Show page A" />

ナビゲーション pageA.page.xml:

<page view-id="/pageA.xhtml">
<navigation>
    <rule if-outcome="showPageB">
        <redirect view-id="/pageB.xhtml" />
    </rule>
</navigation>
</page>

pageBの場合も非常に似ています。

会話のタイムアウトについては、1h に設定しています。ここで読んだように、バックグラウンドでの会話のみを目的としているため、無関係であることに注意してください。スタックトレースは次のとおりです。

Error 500--Internal Server Error

    java.lang.IllegalArgumentException: Stack must not be null
    at org.jboss.seam.core.ConversationEntry.(ConversationEntry.java:45)
    at org.jboss.seam.core.ConversationEntries.createConversationEntry(ConversationEntries.java:53)
    at org.jboss.seam.core.Manager.createConversationEntry(Manager.java:664)
    at org.jboss.seam.core.Manager.beforeRedirect(Manager.java:836)
    at org.jboss.seam.faces.FacesManager.beforeRedirect(FacesManager.java:66)
    at org.jboss.seam.faces.FacesManager.redirect(FacesManager.java:182)
    at org.jboss.seam.faces.Navigator.redirect(Navigator.java:55)
    at org.jboss.seam.navigation.RedirectNavigationHandler.navigate(RedirectNavigationHandler.java:61)
    at org.jboss.seam.navigation.Rule.execute(Rule.java:101)
    at org.jboss.seam.navigation.Navigation.navigate(Navigation.java:58)
    at org.jboss.seam.navigation.Pages.navigate(Pages.java:203)
    at org.jboss.seam.jsf.SeamNavigationHandler.handleNavigation(SeamNavigationHandler.java:42)
    at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:130)
    at javax.faces.component.UICommand.broadcast(UICommand.java:387)
    at org.ajax4jsf.component.AjaxViewRoot.processEvents(AjaxViewRoot.java:324)
    at org.ajax4jsf.component.AjaxViewRoot.broadcastEvents(AjaxViewRoot.java:299)
    at org.ajax4jsf.component.AjaxViewRoot.processPhase(AjaxViewRoot.java:256)
    at org.ajax4jsf.component.AjaxViewRoot.processApplication(AjaxViewRoot.java:469)
    at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:82)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:100)
    at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:265)
    at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:227)
    at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:125)
    at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:292)
    at weblogic.servlet.internal.TailFilter.doFilter(TailFilter.java:26)
    at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:56)
    at org.ajax4jsf.webapp.BaseFilter.doFilter(BaseFilter.java:530)
    at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:56)
    at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:83)
    at org.jboss.seam.web.IdentityFilter.doFilter(IdentityFilter.java:40)
    at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
    at org.jboss.seam.web.MultipartFilter.doFilter(MultipartFilter.java:90)
    at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
    at org.jboss.seam.web.ExceptionFilter.doFilter(ExceptionFilter.java:64)
    at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
    at org.jboss.seam.web.RedirectFilter.doFilter(RedirectFilter.java:45)
    at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
    at org.ajax4jsf.webapp.BaseXMLFilter.doXmlFilter(BaseXMLFilter.java:178)
    at org.ajax4jsf.webapp.BaseFilter.handleRequest(BaseFilter.java:290)
    at org.ajax4jsf.webapp.BaseFilter.processUploadsAndHandleRequest(BaseFilter.java:388)
    at org.ajax4jsf.webapp.BaseFilter.doFilter(BaseFilter.java:515)
    at org.jboss.seam.web.Ajax4jsfFilter.doFilter(Ajax4jsfFilter.java:56)
    at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
    at org.jboss.seam.web.LoggingFilter.doFilter(LoggingFilter.java:60)
    at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
    at org.jboss.seam.web.HotDeployFilter.doFilter(HotDeployFilter.java:53)
    at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
    at org.jboss.seam.servlet.SeamFilter.doFilter(SeamFilter.java:158)
    at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:56)
    at weblogic.servlet.internal.RequestEventsFilter.doFilter(RequestEventsFilter.java:27)
    at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:56)
    at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3592)
    at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321)
    at weblogic.security.service.SecurityManager.runAs(SecurityManager.java:121)
    at weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2202)
    at weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2108)
    at weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1432)
    at weblogic.work.ExecuteThread.execute(ExecuteThread.java:201)
    at weblogic.work.ExecuteThread.run(ExecuteThread.java:173)
4

3 に答える 3

1

StackTraceとユースケースを見た後(ランダムなクリック数の後)

FacesManages.beforeRedirect(StackTraceで表示)のドキュメントを見てみましょう

ブラウザリダイレクトの期間中、一時的な会話を長時間の会話に一時的にプロモートします

それでは、beforeRedirectメソッドのコードを見てみましょう。

if (isDifferentConversationId(currentPage, targetPage))
    updateCurrentConversationId(targetPage.getConversationId());

..。

updateCurrentConversationIdは、 nullであってはならないスタックの作成を担当します。StackTraceをもう一度参照してください。

public void updateCurrentConversationId(String id) {
    if (id != null && id.equals(currentConversationId)) {
     // The conversation id has not changed, do nothing       
     return;
  }

上記のコードの後に​​、スタックが作成されます。したがって、ブラウザのリダイレクトの継続時間(ランダムなクリック数によって引き起こされる)、またはあるページから別のページへのリダイレクト、またはその逆のナビゲーションを処理するときのSeamのバグのために、会話IDが変更されていないと思います。

ページルールごとに次の手順を試してください(timeout = "0"を参照)

<page view-id="/pageA.xhtml" timeout="0">
    <navigation>
        <rule if-outcome="showPageB">
            <redirect view-id="/pageB.xhtml" />
        </rule>
    </navigation>
</page>

私は今それがうまくいくことを期待しています!しかし、そうでない場合は、今、あなたはあなたがあなたの例外を得る理由を知っています

アップデート

回避策として<end-conversation/>を試してください(各ページ)

<page view-id="/pageA.xhtml">
    <navigation>
        <rule if-outcome="showPageB">
            <end-conversation/>
            <redirect view-id="/pageB.xhtml" />
        </rule>
    </navigation>
</page>

または(リダイレクト前を参照)

<page view-id="/pageA.xhtml">
    <navigation>
        <rule if-outcome="showPageB">
            <end-conversation before-redirect="true"/>
            <redirect view-id="/pageB.xhtml" />
        </rule>
    </navigation>
</page>

今、私はそれがうまくいくことを願っています!

編集

beforeRedirectメソッドで述べたように

ブラウザリダイレクトの期間中、一時的な会話を長時間実行される会話に一時的にプロモートします。リダイレクト後、会話は一時的な会話に降格されます。

pageBに移動したときに#{conversation.longRunning}がtrueを出力する理由を説明します。リダイレクトによって引き起こされた「長時間の会話」は、レンダリング応答フェーズの後で破棄する必要があります。

リダイレクトを使用する場合、Seamは会話IDパラメーターをURLに追加します。

SeaminActionの本には

Seamライフサイクルの開始時に、SeamはURLパラメータで会話IDを探します

ただし、pageAに戻ると、同じ会話IDパラメーターが再び表示されるため、URLに誰も含まれていない場合にSeamが新しいパラメーターを作成するだけだと思います。また、長時間実行される会話にはそれぞれ独自のタイムアウト期間があるため、長時間実行される会話は存続します。

私が言ったことが真実かどうかを確認するには、次のようにします

  • グローバルタイムアウト期間を5秒(5000ミリ秒)に短縮

..。

<core:manager conversation-timeout="5000"/>

ページごとに、#{conversation.timeout}の出力を確認してください。5秒または5000ミリ秒のようなものが表示されると思います。5秒(約10秒)以上待ってから、ボタンを押して再度リダイレクトします。また、会話IDパラメータが変更されているかどうかを確認してください。

于 2010-04-13T15:27:40.650 に答える
1

まず第一に、問題をデバッグしようとするときに、関連するコードとスタック トレースを確認することは常に役に立ちます。

したがって、最初の質問にはお答えできません。ただし、会話モデルがどのように機能するかを説明しようと思います。

これは Seam in Action ブックからのものです。

@ScopeType.EVENT = Goes from Restore View to Render Response, but not redirect @ScopeType.CONVERSATION = Goes from Restore VIew to Render Response, and redirect. If long-running conversation, then it spans multiple JSF life cycles.

a.xhtmlそれで、あなたがボタンを押してComponentA、そこにいくつかのデータを取り込んで埋めると想像してみてください。注入して使用するこのコンポーネントb.xhtml :

Push commandbutton in a.xhtml performing post, putting some data in ComponentA 次に、次のページ ( b.xhtml) にリダイレクトします。ComponentA

@Name("componentB")
@Scope(ScopeType.CONVERSATION)
public class ComponentB {
    @In(create=true)
    ComponentA componentA; //OK
}

したがって、再びb.xhtml注入できることを期待して別のボタンを押すComponentAと、失敗します。すなわち:

@Name("componentC")
@Scope(ScopeType.CONVERSATION)
public class ComponentC {
    @In(create=true)
    ComponentA componentA; //Injection of the component you really want fails (you will get default component)
}

そのため、現在バックグラウンドで seam が新しい cid を作成し、以前の cid を終了しています。これは、会話スコープのコンポーネントが 1 つの要求しか有効にできないためです。

于 2010-04-13T13:50:41.650 に答える
0

ずっと前にその情報を提供する必要がありました。これで、何が問題なのかがより明確になりました。

まず第一に、そのような空のアクションで commandButton を使用しないでください。pages.xml に次のように記述します。

<page view-id="/pageA.xhtml">
<navigation>
    <rule if-outcome="showPageB">
        <redirect view-id="/pageB.xhtml" />
    </rule>
</navigation>
</page>

これは通常、次のような showPageB を返すアクションがあることを意味します。

public String someAction() {
    //Do something complex
    return "showPageB";
}

とにかく、あなたの問題に戻ります。自分に好意を持って、Seam コンポーネントを作成してください。

@Name("myComponent")
public Class MyComponent {

public String showPageB() {
    return "showPageB";
}

public String showPageA() {
    return "showPageA";
}

}

pages.xml を次のように変更します。

<page view-id="/pageA.xhtml">
<navigation from action="#{myComponent.showPageB}">
    <redirect view-id="/pageB.xhtml" />
</navigation>

<navigation from action="#{myComponent.showPageA}">
    <redirect view-id="/pageA.xhtml" />
</navigation>

<!-- OR you can do like this -->
<navigation from action="#{myComponent.showPageB}">
    <rule if-outcome="showPageA">
        <redirect view-id="/pageA.xhtml" />
    </rule>
    <rule if-outcome="showPageB">
        <redirect view-id="/pageA.xhtml" />
    </rule>
</navigation>
</page>

次に、xhtmlh:commandButtonを次のように変更します

<h:commandButton action="#{myComponent.showPageA}" value="showA"/>
<h:commandButton action="#{myComponent.showPageB}" value="showB"/>
于 2010-04-14T07:57:10.470 に答える