1

我们在基于 JSF 的 Java Web 应用程序中不断收到以下异常,谷歌搜索表明它可能是由应用程序范围的 jsf 托管 bean 可序列化引起的。

 java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException: org.apache.catalina.session.StandardSessionFacade
    at java.io.ObjectInputStream.readObject0(Unknown Source)
    at java.io.ObjectInputStream.defaultReadFields(Unknown Source)
    at java.io.ObjectInputStream.readSerialData(Unknown Source)
    at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
    at java.io.ObjectInputStream.readObject0(Unknown Source)
    at java.io.ObjectInputStream.readObject(Unknown Source)
    at org.apache.catalina.session.StandardSession.readObject(StandardSession.java:1509)
    at org.apache.catalina.session.StandardSession.readObjectData(StandardSession.java:998)
    at org.apache.catalina.session.StandardManager.doLoad(StandardManager.java:394)
    at org.apache.catalina.session.StandardManager.load(StandardManager.java:321)
    at org.apache.catalina.session.StandardManager.start(StandardManager.java:648)
    at org.apache.catalina.core.ContainerBase.setManager(ContainerBase.java:446)
    at org.apache.catalina.core.StandardContext.start(StandardContext.java:4631)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:799)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:779)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:601)
    at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:675)
    at org.apache.catalina.startup.HostConfig.deployDescriptors(HostConfig.java:601)
    at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:502)
    at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1317)
    at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:324)
    at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:142)
    at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1065)
    at org.apache.catalina.core.StandardHost.start(StandardHost.java:840)
    at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1057)
    at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:463)
    at org.apache.catalina.core.StandardService.start(StandardService.java:525)
    at org.apache.catalina.core.StandardServer.start(StandardServer.java:754)
    at org.apache.catalina.startup.Catalina.start(Catalina.java:595)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:289)
    at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:414)
Caused by: java.io.NotSerializableException: org.apache.catalina.session.StandardSessionFacade
    at java.io.ObjectOutputStream.writeObject0(Unknown Source)
    at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
    at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
    at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
    at java.io.ObjectOutputStream.writeObject0(Unknown Source)
    at java.io.ObjectOutputStream.writeObject(Unknown Source)
    at org.apache.catalina.session.StandardSession.writeObject(StandardSession.java:1585)
    at org.apache.catalina.session.StandardSession.writeObjectData(StandardSession.java:1015)
    at org.apache.catalina.session.StandardManager.doUnload(StandardManager.java:528)
    at org.apache.catalina.session.StandardManager.unload(StandardManager.java:469)
    at org.apache.catalina.session.StandardManager.stop(StandardManager.java:678)
    at org.apache.catalina.core.StandardContext.stop(StandardContext.java:4882)
    at org.apache.catalina.core.ContainerBase.removeChild(ContainerBase.java:936)
    at org.apache.catalina.startup.HostConfig.undeployApps(HostConfig.java:1359)
    at org.apache.catalina.startup.HostConfig.stop(HostConfig.java:1330)
    at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:326)
    at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:142)
    at org.apache.catalina.core.ContainerBase.stop(ContainerBase.java:1098)
    at org.apache.catalina.core.ContainerBase.stop(ContainerBase.java:1110)
    at org.apache.catalina.core.StandardEngine.stop(StandardEngine.java:468)
    at org.apache.catalina.core.StandardService.stop(StandardService.java:604)
    at org.apache.catalina.core.StandardServer.stop(StandardServer.java:788)
    at org.apache.catalina.startup.Catalina.stopServer(Catalina.java:408)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.apache.catalina.startup.Bootstrap.stopServer(Bootstrap.java:338)
    at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:416)

在某些情况下,使用 @ManagedProperty 注释将有问题的托管 bean 注入会话范围的 bean。

这是一种不好的做法,还是我没有得到的其他东西?

4

3 回答 3

0

嗯...据我了解,@ApplicationScoped只要部署了应用程序,托管 bean 就会存在。换句话说,我认为您不需要在需要时存储和恢复 bean。它应该一直在那里。

与其将@ApplicationScopedbean 作为bean 注入@ManagedProperty@SessionScoped不如尝试将其注入@RequestScopedbean,然后将该@RequestScopedbean 注入@SessionScopedbean。:)

于 2012-06-22T08:50:11.970 回答
0

这是因为 JSF 托管 bean 工具没有与 Java 序列化集成。如果aBean 依赖于anotherBean,则将anotherBean 的实例注入到aBean 中。由于序列化一个对象也会序列化它的字段,anotherBean 也会被序列化,这充其量是浪费内存,最坏的情况是很难实现(因为它可能具有不可序列化的依赖项......)。

像 CDI 或 Spring 这样的依赖注入容器将通过将委托给当前 anotherBean 的可序列化代理注入到 aBean 中来解决该问题。这就是为什么应该将支持 bean 保存在不同的 DI 容器中的原因之一。(在 JSF 中使用 CDI 或 Spring 管理的 bean 非常容易)。

编辑:我对被锁定在 Java EE 5 表示同情。在这种情况下,您可能会:

  1. 不要将对应用程序范围的 bean 的引用保留为依赖项,而是在需要时按名称查找它。
  2. 注入应用程序范围 bean 的可序列化代理(或使应用程序范围 bean 本身可序列化)。这将涉及挂钩到序列化机制以按名称序列化 bean,并在反序列化时通过查找重建它。
  3. 将 bean 一分为二:一个对象用于依赖项(请求范围),另一个对象用于状态(会话范围)。就我个人而言,我发现这对于有意义的支持豆的封装来说既麻烦又令人望而却步,但这是一个口味问题。
于 2012-06-22T12:08:45.230 回答
0

是 Tomcat的org.apache.catalina.session.StandardSessionFacade实现HttpSession。因此,此异常表明您在一个视图/会话范围的托管 bean 中具有以下属性:

private HttpSession session;

这是完全错误的。你不应该那样做。同样的故事适用于FacesContext及其ExternalContext所有工件。它们永远不应该被声明为托管 bean 的属性,而总是在线程本地范围内声明(即在与您需要它们的地方完全相同的方法块内)。

于 2013-05-20T13:43:46.980 回答