2

After activating HA on Payara (Hazelcast) I have noticed the following WARN messages in the log:

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

Digging into this I have ended up with button for manual serialization of the @ViewScope beans contained in the sessionScope['com.sun.faces.application.view.activeViewMaps'] Map in order to locate the beans that cause this issue.

It turned out that the issue is caused by usage of the @EJB in @ViewScoped beans. There are several posts here that discuss this issue, but no one seems to provide a solution for clustered environment.

So basically there is a main question: how to properly use @EJB (SLSB) in JSF @VeiwScoped CDI beans in the clustered environment?

One of the possible solutions I saw – is something like this one: https://stackoverflow.com/a/10145618/2261312

The idea of the here-above mentioned solution – just to split ViewScoped bean in two beans: @ViewScoped with actual view-related logic, and EJB beans move to the separate @RequestScoped bean, and inject the @RequestScoped bean into @ViewScoped bean in order to get access to @EJB services.

But this look absolutely weird from the code-syntax / design point of view… Any other suggestions here?

Thanks!

Used software: JSF 2.3.3 (Mojarra), Payara Server 4.1.2.174 (Full), Hazelcast based cluster

And the links I have found so far:


Update 1:

I did several additional tests and have found out, that even though WARN message StandardSession: Cannot serialize session attribute com.sun.faces.application.view.activeViewMaps for session ... appears in the log, cluster works fine, and end-user can switch between cluster nodes without having any issues with proper functionality of the ViewScoped CDI Beans in the JSF app: SLSB injected with @EJB still work even after fail-over to other cluster nodes.

Thus basically the question now is the following: should this WARN message be ignored, or it anyway has to be addressed?

Few words about test case scenario:

1) The deployment includes three servers:

  • Server 1: Payara DAS + Payara Cluster Node 1
  • Server 2: Payara Cluster Node 2
  • Server 3: Nginx which acts as revers-proxy + load-balancer and distributes traffic between nodes

2) JSF Application:

2.1) JSF View:

<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 {
...
}

This works absolutely fine in clustered environment even despite WARN message.

AndrewG10i
  • 661
  • 1
  • 6
  • 21
  • You mention @ EJB, I assume you're injecting enterprise beans with that annotation into the JSF beans, doesn't adding CDI capabilities to those enterprise beans and then injecting them by using @ Inject instead of @ EJB help? – jpangamarca Dec 27 '17 at 13:57
  • Make it transient? – Kukeltje Dec 27 '17 at 18:13
  • 1) Re `@Inject` I think I have tried it as well - didn't help, but I will double check. 2) Re "transient" - I think I read somewhere, that in case of deserialization transient @EJB properties are not being injected again. But actually I will just try to reproduce such scenario and see how it works. Will post my findings shortly! Thank you! – AndrewG10i Dec 29 '17 at 09:30
  • So I have checked suggestions and I have found out: 1) Both `@Inject` and `@EJB` annotations give the same exception: `java.io.NotSerializableException: com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate`; 2) Using `@EJB transient private ...` helps with exception, but the property is not being injected on other cluster nodes, thus this is can not work as solution; 3) During my tests I have noticed, that even though warning `StandardSession: Cannot serialize session attribute com.sun.faces.application.view.activeViewMaps` is appearing - everything works fine. See my "Update 1" – AndrewG10i Jan 05 '18 at 07:57

0 Answers0