Multiple browser tabs or windows with the same Vie

2019-02-19 14:44发布

问题:

Using Payara Server 4.1.2.174 with mojarra 2.2.15.

I have a simple Named Bean with scope javax.faces.view.ViewScoped.

import java.io.Serializable;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.PostConstruct;
import javax.faces.view.ViewScoped;
import javax.inject.Named;


@Named
@ViewScoped
public class SimpleBean implements Serializable
{
    private final Logger logger = Logger.getLogger(SimpleBean.class.getName());

    @PostConstruct
    private void init()
    {
        logger.log(Level.SEVERE, "{0}.init()", this);
    }

    private String name;

    public String getName()
    {
        return name;
    }

    public void setName(String name)
    {
        this.name = name;
    }

    public String action()
    {
        logger.log(Level.SEVERE, "{0}.action()", this);
        logger.log(Level.SEVERE,"====================");
        logger.log(Level.SEVERE, "name: {0}", getName());
        logger.log(Level.SEVERE,"====================");
        return "submit";
    }
}

So I have a simple index.xhtml page with form.

<h:form>
  <h:inputText value="#{simpleBean.name}"></h:inputText>
  <h:link value="To submit" outcome="submit"/>
  <h:commandButton value="Welcome Me" action="#{simpleBean.action()}"/>
</h:form>

I can open index.xhtml in two different browser tabs or windows. So, I have the following log:

Severe: solvo.ee.beans.SimpleBean@2adafd68.init()
Finest: Handling PostConstructViewMapEvent
Finest: Handling PreDestroyViewMapEvent
Finest: Destroying @viewscoped beans from view map: {simpleBean=solvo.ee.beans.SimpleBean@2adafd68}
Severe: solvo.ee.beans.SimpleBean@49a86248.init()
Finest: Handling PostConstructViewMapEvent
Finest: Handling PreDestroyViewMapEvent
Finest: Destroying @viewscoped beans from view map: {simpleBean=solvo.ee.beans.SimpleBean@49a86248}

As we can see there are two different instances of SimpleBean. After that I submit the form of the first tab.

Severe: solvo.ee.beans.SimpleBean@2adafd68.action()
Severe: ====================
Severe: name: First tab
Severe: ====================
Finest: Handling PreDestroyViewMapEvent
Finest: Destroying @viewscoped beans from view map: {simpleBean=solvo.ee.beans.SimpleBean@2adafd68}
Finest: Handling PreDestroyViewMapEvent
Finest: Destroying @viewscoped beans from view map: {}

If I try to submit form of the second tab the stored earlier instance of SimpleBean (solvo.ee.beans.SimpleBean@49a86248) won't be used, instead the ViewScopeContextManager will create a new instance of SimpleBean class, as we can see in log:

Severe: solvo.ee.beans.SimpleBean@4797f115.init()
Severe: solvo.ee.beans.SimpleBean@4797f115.action()
Severe: ====================
Severe: name: Second tab
Severe: ====================
Finest: Handling PreDestroyViewMapEvent
Finest: Destroying @viewscoped beans from view map: {simpleBean=solvo.ee.beans.SimpleBean@4797f115}
Finest: Handling PreDestroyViewMapEvent
Finest: Destroying @viewscoped beans from view map: {}

I have checked the code of the com.sun.faces.application.view.ViewScopeContextManager.copyViewScopeContextsFromSession method and as I understand this behavior is normal. However If i store request parameters or another important data in my bean I will loose it because the instance will be lost after submitting the first form.

Is there a solution to keep bean associated with the second tab primarily (in my example solvo.ee.beans.SimpleBean@49a86248)?

回答1:

It seems this is a bug with Mojarra and will be fixed in 2.3.10 according to this post: https://github.com/eclipse-ee4j/mojarra/issues/4509#issuecomment-453188481

From the same thread, it looks like Payara have applied the patched without waiting for the 2.3.10 release. Does upgrading to the patched Payara solve the problem for you?