集群环境中的ViewScoped CDI bean中的EJB(Payara上的Hazelcast) - 提供NotSerializableException WARN

时间:2017-12-25 05:25:02

标签: jsf jsf-2 ejb view-scope

在Payara(Hazelcast)上激活HA后,我注意到日志中有以下WARN消息:

[2017-12-12T15:12:31.266+0800] [Payara 4.1] [WARNING] [] [javax.enterprise.web.core] [tid: _ThreadID=63 _ThreadName=http-thread-pool::http-listener-2(2)] [timeMillis: 1513062751266] [levelValue: 900] [[
  StandardSession: Cannot serialize session attribute com.sun.faces.application.view.activeViewMaps for session 9914fe69fd67044327585dc07409]]

深入研究这个问题,我最终得到了@ViewScope地图中包含的sessionScope['com.sun.faces.application.view.activeViewMaps'] bean的手动序列化按钮,以找到导致此问题的bean。

事实证明,问题是由@EJB bean中@ViewScoped的使用引起的。这里有几篇文章讨论了这个问题,但似乎没有人为集群环境提供解决方案。

所以基本上有一个主要问题:如何在集群环境中的JSF @EJB CDI bean中正确使用@VeiwScoped(SLSB)?

我看到的一种可能的解决方案 - 就像这样: https://stackoverflow.com/a/10145618/2261312

上面提到的解决方案的想法 - 只是将ViewScoped bean拆分为两个bean:@ViewScoped与实际的视图相关逻辑,EJB bean移动到单独的@RequestScoped bean,并将@RequestScoped bean注入@ViewScoped bean,以便访问@EJB个服务。

但从代码语法/设计的角度来看,这看起来很奇怪......这里还有其他建议吗?

谢谢!

二手软件:JSF 2.3.3(Mojarra),Payara Server 4.1.2.174(完整版),基于Hazelcast的集群

到目前为止我找到的链接:

更新1:

我做了几个额外的测试并且发现,即使WARN消息StandardSession: Cannot serialize session attribute com.sun.faces.application.view.activeViewMaps for session ...出现在日志中,集群也能正常工作,最终用户可以在集群节点之间切换,而不会出现任何问题。 JSF应用程序中的ViewScoped CDI Bean:注入@EJB的SLSB即使在故障转移到其他群集节点后仍然有效。

因此,基本上现在的问题是:如果忽略此WARN消息,或者无论如何必须解决它?

关于测试用例场景的几句话:

1)部署包括三台服务器:

  • 服务器1:Payara DAS + Payara群集节点1
  • 服务器2:Payara群集节点2
  • 服务器3:Nginx充当反向代理+负载均衡器并在节点之间分配流量

2)JSF应用程序:

2.1)JSF查看:

<ui:composition>
    <ui:define name="content">
        <h:form id="ft1">
            mark2 = #{testBean.mark2}<br/>
            mark3 = #{testBean.mark3}<br/>        
            <p:commandButton value="TEST SER" action="#{testBean.test1()}" /><br/>
            <p:commandButton value="TEST2" action="#{testBean.test2()}" update="@form"/>
        </h:form>
    </ui:define>
</ui:composition>

2.2)JSF ViewScope Bean:

package ua.local.beans;

import ....
import javax.faces.view.ViewScoped;
import ....


@Named
@ViewScoped
public class TestBean implements Serializable {

    private static final long serialVersionUID = -4596312102341014148L;

    @EJB
    private LogDao _logDao;

    private long mark2 = 0;
    private long mark3 = 0;

    public void test1() {
        try {
            File serFile = File.createTempFile("debug_", ".ser");
            FileOutputStream fileOut = new FileOutputStream(serFile);
            ObjectOutputStream out = new ObjectOutputStream(fileOut);
            out.writeObject(this);
            out.close();
            fileOut.close();
            System.out.printf("TEST: Serialized data is saved in " + serFile.getAbsolutePath());
        } catch (Exception i) {
            i.printStackTrace();
        }

    }

    public void test2() {
        System.out.println(">> found LOGS: " + _logDao.findAll().size());
        mark2 = mark3;
        mark3 = System.currentTimeMillis();
    }

    public long getMark2() {
        return mark2;
    }

    public long getMark3() {
        return mark3;
    }
}

2.3)SLSB:

@Stateless
public class LogDaoMongoImpl extends AbstractMongoDAO<Log> implements LogDao, Serializable {
...
}

即使有WARN消息,这在集群环境中也能正常工作。

0 个答案:

没有答案