代码之家  ›  专栏  ›  技术社区  ›  Markos Fragkakis

没有长时间运行的对话-IllegalArgumentException:堆栈不能为null

  •  3
  • Markos Fragkakis  · 技术社区  · 15 年前

    但是 ,即使我有 没有长时间的对话 定义,在随机的点击次数之后,并且-我想-在随机的秒数(~10秒-60秒)之后,我在这篇文章的结尾得到了一个可爱的例外。

    1. 当我第一次看到我的应用程序时,url是 http://localhost:7001/myapp
    2. 当我点击页面a.xhtml,我最终在“pageB.xhtml?cid=26“。这是正常的,因为Seam将第一个请求的临时会话延长到重定向的renderResponse阶段。因此,它使用扩展临时会话的cid(会话Id)来查找任何传播的参数。

    3. 当我点击页面b.xhtml,我最终在pageA.xhtml?cid=26

    新的扩展临时会话也得到了相同的cid。这是正常的,因为会话在post之后的前一个重定向结束,而不是数字26可以随意用作cid。

    这些都对吗?如果是,为什么会发生这种情况:如果我重新键入应用程序的家庭地址(显示pageA)并重新单击,我最终会在pageB.xhtml?cid=29,与26不同。但是26已经在上一个RenderResponse阶段结束,在我重新键入url之前。为什么不用它来代替29?

    所以,补充两个问题:

    1. cid到底怎么了?它基于什么变化?

    更新:

    附加信息:我在第A页中使用类似的h:command按钮:

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

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

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

    和pageB非常相似。

    here ,仅用于背景对话。堆栈跟踪如下:

    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)
    
    3 回复  |  直到 15 年前
        1
  •  1
  •   Shervin Asgari    15 年前

    首先,在尝试调试问题时,查看相关代码和stacktrace总是很有帮助的。

    因此,我不能回答你的第一个问题。不过,我将尝试解释会话模型是如何工作的。

    这是行动手册中的Seam:

    @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 成分a

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

    如果你现在按下另一个按钮 b、 xhtml 希望能够注入 成分a 同样,这将失败。 即:

    @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)
    }
    

        2
  •  1
  •   Arthur Ronald    15 年前

    在看到StackTrace和用例之后(在随机点击次数之后)

    让我们看看FacesManages.beforeRedirect(如StackTrace所示)文档

    将临时会话临时升级为长时间会话 在浏览器重定向期间

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

    ...

    updateCurrentConversationId负责创建堆栈 再看看你的踪迹

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

    在上面显示的代码之后,将创建堆栈。所以我想 会话id未更改 因为 浏览器重定向的持续时间 (由随机点击次数引起)或者甚至是Seam错误,当处理从一个页面到另一个页面的重定向导航时,反之亦然

    试试下面的方法 对于每个

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

    更新

    <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>
    

    现在我希望它工作良好!

    编辑

    如前所述

    将临时对话升级为长期对话 在浏览器重定向期间。重定向后,会话将降级回临时会话。

    当使用重定向时,Seam将会话id paratemer附加到URL。

    在Seam生命周期的开始,Seam看起来 对于URL参数中的会话id

    但因为当你回到pageA,你又看到了 相同的会话id参数 我想是的 Seam只是在url不包含任何人时创建一个新的 . 因为每个长时间运行的会话都有自己的超时时间,所以长时间运行的会话将保持活动状态。

    为了证实我所说的是不是真的,请按以下步骤做

    • 将全局超时时间减少到5秒(5000毫秒)

    ...

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

        3
  •  0
  •   Shervin Asgari    15 年前

    你早就应该提供这些信息了。现在更清楚问题是什么了。

    <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";
    }
    
    }
    

    改变你的想法页面.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>
    

    然后更改xhtml h:commandButton

    <h:commandButton action="#{myComponent.showPageA}" value="showA"/>
    <h:commandButton action="#{myComponent.showPageB}" value="showB"/>