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

发布于 2024-08-28 21:02:05 字数 6732 浏览 9 评论 0原文

我有一个非常简单的应用程序,在 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

26相同的 cid 被赋予新的扩展临时对话。这是正常的,因为对话在上一个重定向后结束时结束,并且数字 26 不是可以免费用作 cid 的。

这一切都正确吗?如果是,为什么会发生这种情况:如果我重新输入应用程序主地址(显示 pageA)并重新单击,我最终会出现 pageB.xhtml?cid=29,该数字与 26 不同。但是 26 已结束在上一个 RenderResponse 阶段之后,我重新输入 url。为什么不使用它而是使用29?

因此,要解决两个问题:

  1. 即使我没有开始任何长时间运行的对话,为什么我会遇到异常?
  2. cid 到底发生了什么?改变的依据是什么?

干杯,

更新:

中使用这样的 h:commandButtons,

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

附加信息:我在页面 A:和页面 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)

I have a very simple application with just 2 pages on WebLogic 10.3.2 (11g), Seam 2.2.0.GA. I have a command button in each, which makes a redirect-after-post to the other. This works well, as I see the URL of the current page I am seeing in the address bar.

BUT, even though I have no long-running conversations defined, after a random number of clicks, and - I think - after a random number of seconds (~10s - 60s) I get the lovely exception at the end of this post.

Now, if I have understood how temporary conversations work when redirecting this happens:

  1. When I first see my application, the url is http://localhost:7001/myapp
  2. When I click the button in pageA.xhtml, I end up in "pageB.xhtml?cid=26". This is normal because Seam extends the temporary conversation of the first request to last until the renderResponse phase of the redirect. So, it uses the cid (Conversation Id) of the extended temporary conversation to find any propagated parameters.

  3. When I click the button in pageB.xhtml, I end up in pageA.xhtml?cid=26

The same cid was given to the new extended temporary conversation. This is normal because the conversation ended at the end of the previous redirect-after-post, and not the number 26 is free to use as a cid.

Is this all correct? If yes, why does this happen: If I re-type the applications home address (showing pageA) and re-click, I end up in pageB.xhtml?cid=29, which is a different number than 26. But 26 has ended after the previous RenderResponse phase, befire I re-types the url. Why is it not used instead of 29?

So, to sup up, 2 questions:

  1. Why do I get the exception, even though I have not started any long-running conversations?
  2. What happens exactly with the cid? On what basis does it change?

Cheers,

UPDATE:

Additional information: I use h:commandButtons like this in page A:

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

and in page B

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

navigation pageA.page.xml:

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

and a very similar for pageB.

As for the conversation timeout, I have set it to 1h. Note that it is irrelevant, because as I read here, it is only meant for background conversations. The stacktrace follows:

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)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

一个人的旅程 2024-09-04 21:02:05

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

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

这是来自《Seam in Action》一书:


@ScopeType.EVENT = 从恢复视图转到渲染响应,但不重定向
@ScopeType.CONVERSATION = 从“恢复视图”转到“渲染响应”,然后重定向。如果对话长时间运行,那么它会跨越多个 JSF 生命周期。

因此,假设您在 a.xhtml 中,按下一个按钮,该按钮将获取 ComponentA 并在其中填充一些数据。您要在 b.xhtml 中注入和使用该组件
即:

在 a.xhtml 中按下命令按钮执行 post,将一些数据放入 ComponentA
现在您重定向到使用 ComponentA 的下一页 (b.xhtml)

@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,因为会话范围组件只能处理一个请求。

First of all, it is always helpful to see the relevant code and stacktrace when trying to debug a problem.

Thus I cannot give an answer to your first question. However, I will try to explain how the conversation model works.

This is from the Seam in Action book:


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

So imagine you are in a.xhtml you push a button that will take ComponentA and fill some data in it. This component you want to inject and use in b.xhtml
ie:

Push commandbutton in a.xhtml performing post, putting some data in ComponentA
Now you redirect to next page (b.xhtml)which uses the ComponentA

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

So if you now push another button from b.xhtml expecting to be able to inject ComponentA again, that will fail.
ie:

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

So in the background now, seam has created a new cid for you, ending the previous cid because a conversation scoped component can only live one request.

墨小沫ゞ 2024-09-04 21:02:05

查看您的 StackTrace 和用例后(随机点击次数后)

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

在浏览器重定向期间暂时将临时对话升级为长时间运行的对话

,让我们看一下 beforeRedirect 方法的一些代码

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

...

updateCurrentConversationId 负责创建堆栈,该堆栈必须be not null 再次查看您的 StackTrace

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

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

为每个尝试以下页面规则(请参阅 timeout =“0”)

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

我希望现在它可以正常工作!但是,如果没有,现在您知道为什么会出现异常

UPDATE

尝试作为解决方法(针对每个页面)

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

行动中的接缝书说

在 Seam 生命周期开始时,Seam 在 URL 参数中查找对话 ID

但是因为当您返回 pageA 时,您会再次看到相同的对话 id 参数 ,我想当 url 不包含任何人时,Seam 只是创建一个新的。而且由于每个长时间运行的对话都有自己的超时期限,因此您的长时间运行的对话将保持活动状态。

要验证我所说的是否属实,请执行以下操作,

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

...

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

对于每个页面,查看 #{conversation.timeout} 输出。我期望看到类似 5 秒或 5000 毫秒的内容。等待 5 秒以上(约 10 秒),然后按 按钮再次重定向。并查看对话id参数是否已更改。

After seeing your StackTrace and your Use case (after a random number of clicks)

Let's see FacesManages.beforeRedirect (as shown by your StackTrace) documentation

Temporarily promote a temporary conversation to a long running conversation for the duration of a browser redirect

Now, let's see some piece of code of beforeRedirect method

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

...

updateCurrentConversationId is responsible for creating the Stack which must be not null See again your StackTrace

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

After code shown above, your Stack will be created. So i suppose The conversation id has not changed because of The duration of a browser redirect (caused by a random number of clicks) or even a Seam bug when dealing with a navigation with redirect from one page to another and vice-versa

Try the following one for each Page rule (see timeout="0")

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

I expect now it works fine! But, if not, now, you know why you get your exception

UPDATE

Try <end-conversation/> as a workaround (for each page)

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

or (see before-redirect)

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

Now i hope it works fine!

EDIT

As said by beforeRedirect method

Temporarily promote a temporary conversation to a long running conversation for the duration of a browser redirect. After the redirect, the conversation will be demoted back to a temporary conversation.

It explains why #{conversation.longRunning} outputs true when you go to pageB. Your "long running conversation" caused by your redirect should be destroyed after the Render Response phase.

When using a redirect, Seam appends conversation id paratemer to URL.

Seam in Action book says

At the beginning of the Seam life cycle, Seam looks for the conversation id in a URL parameter

But because when you are back to pageA, you see again the same conversation id parameter, I suppose Seam just create a new one when the url does not contain anyone. And because each long running conversation has it own Timeout period, your long running conversation is keeped alive.

To verify whether what i said is true, do as follows

  • reduce global Timeout period to five seconds (5000 milliseconds)

...

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

For each Page, see what #{conversation.timeout} outputs. I expect to see something like Either 5 seconds or 5000 miliseconds. Wait for more than 5 seconds (about 10s) and press button to redirect again. And see whether conversation id parameter has been changed.

瑶笙 2024-09-04 21:02:05

您应该很久以前就提供该信息。现在问题出在哪里更加清楚了。

首先,您不应该使用带有空操作的命令按钮。当您在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>

然后将xhtml h:commandButton更改为

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

You should have provided that information long ago. Now it is much more clear what the problem is.

First of all you shouldn't use a commandButton with an empty action like that. When you in pages.xml write the following:

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

It means normally that you have some action that returns showPageB like this:

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

Anyhow, back to your problem.
Do your self a favor and create a Seam component.

@Name("myComponent")
public Class MyComponent {

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

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

}

Change your pages.xml to this:

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

Then change xhtml h:commandButton to

<h:commandButton action="#{myComponent.showPageA}" value="showA"/>
<h:commandButton action="#{myComponent.showPageB}" value="showB"/>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文