0

我有一个 facelet 在会话超时后 30 秒刷新浏览器窗口,例如

<a4j:region>
<h:form>
<a4j:poll id="poll" interval="#{(session.maxInactiveInterval + 30)*1000}" onbegin="window.document.location.href='/Patrac'"/>
</h:form>
</a4j:region>

重新加载时,facelet 会导致在 SFSB 上调用方法,例如

<ui:define name="title">PATRAC - #{workflowManager.currentWorkflow.screenTitle}</ui:define>

SFSB 是会话范围的。

@SessionScoped

@Stateful

public class WorkflowManager {

    ... 

    public Workflow getCurrentWorkflow() { return currentWorkflow; }

    @PreDestroy public void bye() { System.out.println("Destroying: "+ getClass().getName() +", ID = "+ getId()); }

}

85% 的时间屏幕刷新无意外:

15:56:44,951 INFO  [stdout] (http-/127.0.0.1:8443-1) Destroying: com.patrac.controller.statemachine.WorkflowManager, ID = -1906221148858801782
15:56:44,968 INFO  [com.patrac.filter.NoCacheFilter] (http-/127.0.0.1:8443-1) NoCacheFilter.doFilter() URI: /Patrac/
15:58:01,343 INFO  [stdout] (ContainerBackgroundProcessor[StandardEngine[jboss.web]]) Destroying: com.patrac.controller.statemachine.WorkflowManager, ID = -3546919396833964128
15:58:15,288 INFO  [com.patrac.filter.NoCacheFilter] (http-/127.0.0.1:8443-3) NoCacheFilter.doFilter() URI: /Patrac/index.xhtml
15:58:15,319 INFO  [com.patrac.filter.NoCacheFilter] (http-/127.0.0.1:8443-4) NoCacheFilter.doFilter() URI: /Patrac/
15:58:15,349 WARNING [com.patrac.controller.exceptionhandler.ViewExpiredExceptionHandler] (http-/127.0.0.1:8443-3) Attempt to access an expired view: /index.xhtml from remote host: 127.0.0.1
15:58:15,389 INFO  [com.patrac.filter.NoCacheFilter] (http-/127.0.0.1:8443-4) NoCacheFilter.doFilter() URI: /Patrac/index.xhtml
15:59:45,771 INFO  [stdout] (http-/127.0.0.1:8443-1) Destroying: com.patrac.controller.statemachine.WorkflowManager, ID = -5655846827584878649
15:59:45,777 INFO  [com.patrac.filter.NoCacheFilter] (http-/127.0.0.1:8443-1) NoCacheFilter.doFilter() URI: /Patrac/index.xhtml
15:59:45,800 WARNING [com.patrac.controller.exceptionhandler.ViewExpiredExceptionHandler] (http-/127.0.0.1:8443-1) Attempt to access an expired view: /index.xhtml from remote host: 127.0.0.1
15:59:45,890 INFO  [com.patrac.filter.NoCacheFilter] (http-/127.0.0.1:8443-1) NoCacheFilter.doFilter() URI: /Patrac/index.xhtml
16:00:01,356 INFO  [stdout] (ContainerBackgroundProcessor[StandardEngine[jboss.web]]) Destroying: com.patrac.controller.statemachine.WorkflowManager, ID = 4579100734353654546
16:01:01,363 INFO  [stdout] (ContainerBackgroundProcessor[StandardEngine[jboss.web]]) Destroying: com.patrac.controller.statemachine.WorkflowManager, ID = 4317425328092070112
16:01:16,518 INFO  [com.patrac.filter.NoCacheFilter] (http-/127.0.0.1:8443-3) NoCacheFilter.doFilter() URI: /Patrac/index.xhtml
16:01:16,526 INFO  [com.patrac.filter.NoCacheFilter] (http-/127.0.0.1:8443-8) NoCacheFilter.doFilter() URI: /Patrac/
16:01:16,544 WARNING [com.patrac.controller.exceptionhandler.ViewExpiredExceptionHandler] (http-/127.0.0.1:8443-3) Attempt to access an expired view: /index.xhtml from remote host: 127.0.0.1
16:01:16,572 INFO  [com.patrac.filter.NoCacheFilter] (http-/127.0.0.1:8443-3) NoCacheFilter.doFilter() URI: /Patrac/index.xhtml
16:02:46,894 INFO  [stdout] (http-/127.0.0.1:8443-1) Destroying: com.patrac.controller.statemachine.WorkflowManager, ID = 7360031599060690367
16:02:46,900 INFO  [com.patrac.filter.NoCacheFilter] (http-/127.0.0.1:8443-1) NoCacheFilter.doFilter() URI: /Patrac/index.xhtml
16:02:46,923 INFO  [com.patrac.filter.NoCacheFilter] (http-/127.0.0.1:8443-6) NoCacheFilter.doFilter() URI: /Patrac/
16:02:46,950 WARNING [com.patrac.controller.exceptionhandler.ViewExpiredExceptionHandler] (http-/127.0.0.1:8443-1) Attempt to access an expired view: /index.xhtml from remote host: 127.0.0.1
16:02:46,975 INFO  [com.patrac.filter.NoCacheFilter] (http-/127.0.0.1:8443-1) NoCacheFilter.doFilter() URI: /Patrac/index.xhtml
16:03:01,380 INFO  [stdout] (ContainerBackgroundProcessor[StandardEngine[jboss.web]]) Destroying: com.patrac.controller.statemachine.WorkflowManager, ID = -5741388414554084710
16:04:01,389 INFO  [stdout] (ContainerBackgroundProcessor[StandardEngine[jboss.web]]) Destroying: com.patrac.controller.statemachine.WorkflowManager, ID = -1149102875316717372
16:04:01,395 INFO  [stdout] (ContainerBackgroundProcessor[StandardEngine[jboss.web]]) Destroying: com.patrac.controller.statemachine.WorkflowManager, ID = -7198492156368620025
16:04:17,355 INFO  [com.patrac.filter.NoCacheFilter] (http-/127.0.0.1:8443-7) NoCacheFilter.doFilter() URI: /Patrac/index.xhtml
16:04:17,365 INFO  [com.patrac.filter.NoCacheFilter] (http-/127.0.0.1:8443-8) NoCacheFilter.doFilter() URI: /Patrac/
16:04:17,405 WARNING [com.patrac.controller.exceptionhandler.ViewExpiredExceptionHandler] (http-/127.0.0.1:8443-7) Attempt to access an expired view: /index.xhtml from remote host: 127.0.0.1
16:04:17,460 INFO  [com.patrac.filter.NoCacheFilter] (http-/127.0.0.1:8443-8) NoCacheFilter.doFilter() URI: /Patrac/index.xhtml
16:05:47,769 INFO  [stdout] (http-/127.0.0.1:8443-7) Destroying: com.patrac.controller.statemachine.WorkflowManager, ID = -8106288024707282506
16:05:47,773 INFO  [com.patrac.filter.NoCacheFilter] (http-/127.0.0.1:8443-7) NoCacheFilter.doFilter() URI: /Patrac/index.xhtml
16:05:47,808 INFO  [com.patrac.filter.NoCacheFilter] (http-/127.0.0.1:8443-6) NoCacheFilter.doFilter() URI: /Patrac/
16:05:47,809 WARNING [com.patrac.controller.exceptionhandler.ViewExpiredExceptionHandler] (http-/127.0.0.1:8443-7) Attempt to access an expired view: /index.xhtml from remote host: 127.0.0.1
16:05:47,856 INFO  [com.patrac.filter.NoCacheFilter] (http-/127.0.0.1:8443-7) NoCacheFilter.doFilter() URI: /Patrac/index.xhtml
16:06:01,409 INFO  [stdout] (ContainerBackgroundProcessor[StandardEngine[jboss.web]]) Destroying: com.patrac.controller.statemachine.WorkflowManager, ID = 6737131848251158629
16:07:01,419 INFO  [stdout] (ContainerBackgroundProcessor[StandardEngine[jboss.web]]) Destroying: com.patrac.controller.statemachine.WorkflowManager, ID = -3248726216386741006
16:07:01,423 INFO  [stdout] (ContainerBackgroundProcessor[StandardEngine[jboss.web]]) Destroying: com.patrac.controller.statemachine.WorkflowManager, ID = -7798326820709515585
16:07:18,188 INFO  [com.patrac.filter.NoCacheFilter] (http-/127.0.0.1:8443-8) NoCacheFilter.doFilter() URI: /Patrac/
16:07:18,188 INFO  [com.patrac.filter.NoCacheFilter] (http-/127.0.0.1:8443-1) NoCacheFilter.doFilter() URI: /Patrac/index.xhtml
16:07:18,219 WARNING [com.patrac.controller.exceptionhandler.ViewExpiredExceptionHandler] (http-/127.0.0.1:8443-1) Attempt to access an expired view: /index.xhtml from remote host: 127.0.0.1
16:07:18,250 INFO  [com.patrac.filter.NoCacheFilter] (http-/127.0.0.1:8443-1) NoCacheFilter.doFilter() URI: /Patrac/index.xhtml

但是,有时会发生以下情况:

16:08:48,536 INFO  [stdout] (http-/127.0.0.1:8443-7) Destroying: com.patrac.controller.statemachine.WorkflowManager, ID = 601708170643229812
16:08:48,537 INFO  [com.patrac.filter.NoCacheFilter] (http-/127.0.0.1:8443-7) NoCacheFilter.doFilter() URI: /Patrac/index.xhtml
16:08:48,540 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host]] (http-/127.0.0.1:8443-3) Exception sending request initialized lifecycle event to listener instance of class org.jboss.weld.servlet.WeldListener: javax.ejb.NoSuchEJBException: JBAS016055: EJB has been removed
    at org.jboss.as.weld.ejb.StatefulSessionObjectReferenceImpl.getBusinessObject(StatefulSessionObjectReferenceImpl.java:124) [jboss-as-weld-7.2.0.Alpha1-SNAPSHOT.jar:7.2.0.Alpha1-SNAPSHOT]
    at org.jboss.weld.bean.proxy.EnterpriseBeanProxyMethodHandler.invoke(EnterpriseBeanProxyMethodHandler.java:108) [weld-core-1.1.9.Final.jar:2012-08-06 19:12]
    at org.jboss.weld.bean.proxy.EnterpriseTargetBeanInstance.invoke(EnterpriseTargetBeanInstance.java:56) [weld-core-1.1.9.Final.jar:2012-08-06 19:12]
    at org.jboss.weld.bean.proxy.ProxyMethodHandler.invoke(ProxyMethodHandler.java:105) [weld-core-1.1.9.Final.jar:2012-08-06 19:12]
    at com.patrac.controller.statemachine.WorkflowManager$Proxy$_$$_Weld$Proxy$.toString(WorkflowManager$Proxy$_$$_Weld$Proxy$.java) [Patrac-ejb.jar:]
    at java.lang.String.valueOf(String.java:2854) [rt.jar:1.7.0_07]
    at java.lang.StringBuilder.append(StringBuilder.java:128) [rt.jar:1.7.0_07]
    at org.jboss.weld.context.SerializableContextualInstanceImpl.toString(SerializableContextualInstanceImpl.java:60) [weld-core-1.1.9.Final.jar:2012-08-06 19:12]
    at java.lang.String.valueOf(String.java:2854) [rt.jar:1.7.0_07]
    at java.lang.StringBuilder.append(StringBuilder.java:128) [rt.jar:1.7.0_07]
    at org.jboss.weld.context.beanstore.AttributeBeanStore.attach(AttributeBeanStore.java:109) [weld-core-1.1.9.Final.jar:2012-08-06 19:12]
    at org.jboss.weld.context.AbstractBoundContext.activate(AbstractBoundContext.java:66) [weld-core-1.1.9.Final.jar:2012-08-06 19:12]
    at org.jboss.weld.servlet.WeldListener.requestInitialized(WeldListener.java:141) [weld-core-1.1.9.Final.jar:2012-08-06 19:12]
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143) [jbossweb-7.0.17.Final.jar:]
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) [jbossweb-7.0.17.Final.jar:]
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) [jbossweb-7.0.17.Final.jar:]
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:372) [jbossweb-7.0.17.Final.jar:]
    at org.apache.coyote.http11.Http11AprProcessor.process(Http11AprProcessor.java:897) [jbossweb-7.0.17.Final.jar:]
    at org.apache.coyote.http11.Http11AprProtocol$Http11ConnectionHandler.process(Http11AprProtocol.java:634) [jbossweb-7.0.17.Final.jar:]
    at org.apache.tomcat.util.net.AprEndpoint$Worker.run(AprEndpoint.java:2039) [jbossweb-7.0.17.Final.jar:]
    at java.lang.Thread.run(Thread.java:722) [rt.jar:1.7.0_07]
16:08:48,561 WARNING [com.patrac.controller.exceptionhandler.ViewExpiredExceptionHandler] (http-/127.0.0.1:8443-7) Attempt to access an expired view: /index.xhtml from remote host: 127.0.0.1

堆栈跟踪始终出现在浏览器窗口中,因此在会话超时时浏览器发出请求后会发生这种情况。只有在 SFSB 被销毁的几乎同时(毫秒内)收到请求时才会发生这种情况。它永远不会在注销时发生,尽管 302 REDIRECT 会导致浏览器在 SFSB 被销毁后仅几毫秒内发出请求。似乎不仅时间是一个因素,而且每次发生这种情况时都会抛出 ViewExpiredException 。

似乎正在发生的事情是因为会话超时但 EJB 没有立即删除,当浏览器发出请求时,JBoss 从超时会话中删除 EJB,然后抛出 EJB 已被删除而不是首先删除的异常创建一个新的 EJB 并将其绑定到新会话。

如何处理 NoSuchEJBException,或者更好地完全避免它?

4

2 回答 2

1

通过将 ViewExpiredExceptionHandler 重定向到 facelet viewExpired.xhtml 解决了这个问题。

在此更改之前,ViewExpiredExceptionHandler 被重定向到 Web 应用程序的根目录 /Patrac,并且 web.xml 中的以下条目导致另一个重定向到 index.xhtml:

    <welcome-file-list>
        <welcome-file>index.xhtml</welcome-file>
    </welcome-file-list>

此外,index.xhtml 被配置为刷新到 /Patrac,这将被重定向到 /Patrac/index.xhtml,这将导致 ViewExpiredException,这将导致另一个重定向 /Patrac,这将重定向到欢迎页面,/ Patrac/index.xhtml,全部快速连续。

<a4j:poll id="poll" interval="#{(session.maxInactiveInterval + 30)*1000}" onbegin="window.document.location.href='/Patrac'"/>

通常,没有问题。但是根据 Servlet 规范,会话不一定会在部署描述符中指定的时间完全销毁——存在一些变化。因此,有时当浏览器刷新发生在服务器端会话被销毁的几毫秒内,并且 JBoss 还没有完成清理其状态时,就会抛出 NoSuchEJBExceptions。

将 index.xhtml 中的客户端 ajax 轮询/超时更改为以下内容,并确保 viewExpiredException.xhtml 没有执行任何浏览器刷新/ajax 轮询,从而使问题消失。

<a4j:poll id="poll" interval="#{(session.maxInactiveInterval + 30)*1000}" onbegin="window.document.location.href='/Patrac/viewExpired.xhtml"/>
于 2012-11-01T06:43:40.327 回答
0

尝试使用 StatefulTimeout

 @StatefulTimeout(unit = TimeUnit.MINUTES, value = 30)
于 2012-10-15T11:25:34.670 回答