ViewScoped works like RequestScoped - why?
Asked Answered
L

2

1

I wrote a ViewScoped Managed-Bean and every time I refresh the page in my webbrowser, the Managed-Bean seems to be recreated, article is null, it loads a new article-object and so on. For me it looks like the same behaviour as RequestScoped.

I use Eclipse IDE for Java EE Developers, the newest JDK, Apache Tomcat 7.0.8 and Mojarra 2.0.3.

What is wrong?

Managed-Bean:

...
import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
...
@ManagedBean
@ViewScoped
public class CreateArticle {

    @ManagedProperty(value = "#{index.facade}")
    private PersistenceFacade facade;
    private Article article;
    private Vector<ArtCategory> artcat;

    public CreateArticle() {
        artcat = ArtCategory.listArtCat();
    }

    @PostConstruct
    public void postCreateArticle() {
        if (article == null) {
            try {
                article = facade.createArticle();
            } catch (DAOException e) {
                e.printStackTrace();
            }
        }
    }

    public void setFacade(PersistenceFacade facade) {
        this.facade = facade;
    }

    public Vector<ArtCategory> getArtcat() {
        return artcat;
    }

    public Article getArticle() {
        return article;
    }

    public String save() {
        try {
            facade.save(article);
            facade.commit();
        } catch (DAOException e) {
            e.printStackTrace();
        }
        FacesMessage message = new FacesMessage(
                "Successful!");
        FacesContext.getCurrentInstance().addMessage(null, message);
        return "/testpage.xhtml";
    }

}

createArticle.xhtml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html">
<h:head>
    <title>Create article</title>
</h:head>
<h:body>
    <h1>
        <h:outputText value="System" />
    </h1>
    <h2>
        <h:outputText value="Test1" />
    </h2>
    <h3>
        <h:outputText value="Test2" />
    </h3>
    <h:form>
        <h:panelGrid columns="3">
            <h:outputLabel for="artname">Articlename</h:outputLabel>
            <h:inputText id="artname" value="#{createArticle.article.artname}"
                required="true">
                <f:ajax event="blur" render="artnameMessage" />
            </h:inputText>
            <h:message id="artnameMessage" for="artname" />

            <h:outputLabel for="briefdesc">Brief description</h:outputLabel>
            <h:inputTextarea id="briefdesc"
                value="#{createArticle.article.briefdesc}" required="false">
                <f:ajax event="blur" render="briefdescMessage" />
            </h:inputTextarea>
            <h:message id="briefdescMessage" for="briefdesc" />

            <h:outputLabel for="price">Price</h:outputLabel>
            <h:inputText id="price" value="#{createArticle.article.price}"
                required="true">
                <f:ajax event="blur" render="priceMessage" />
            </h:inputText>
            <h:message id="priceMessage" for="price" />

            <h:outputLabel for="selectartcat">Article Category</h:outputLabel>
            <h:selectOneMenu id="selectartcat"
                value="#{createArticle.article.artcatnr}" required="true">
                <f:selectItems value="#{createArticle.artcat}" var="artcat"
                    itemLabel="#{artcat.name}" itemValue="#{artcat.artcatnr}" />
                <f:ajax event="blur" render="selectartcatMessage" />
            </h:selectOneMenu>
            <h:message id="selectartcatMessage" for="selectartcat" />

            <h:panelGroup />
            <h:commandButton value="Save"
                action="#{createArticle.save}">
                <f:ajax execute="@form" render="@form" />
            </h:commandButton>
            <h:messages globalOnly="true" layout="table" />
        </h:panelGrid>
    </h:form>
</h:body>
</html>
Languet answered 7/3, 2011 at 13:43 Comment(0)
K
6

That's expected behaviour. Surely it will be recreated when you fire brand new HTTP GET requests by refreshing the page in the browser. Otherwise it would act like a session scoped bean and it would make the view scope useless (think about new GET requests in different browser tabs!). It will however not be recreated when you invoke any ajax requests or submit the form in the same view. A request scoped one would be recreated everytime. That's the core point/advantage of a view scoped bean.

Kissee answered 7/3, 2011 at 14:10 Comment(3)
... and I thought all the time a view was defined as being the same page! I mean xyz.xhtml (xyz.jsf) is a view in JSF terms (viewParams, view whatever, ...). Confusing to the bone. Getting better every day reading your posts.Hylo
@Kawu: yes, some terms are full of ambiguity. How to interpret them depends on the point of view ;) More simply put: A view scoped bean lives as long as you're submitting POST requests to it. When you send a GET request to it, a new view scope will be created.Kissee
If you do refresh, you're not on the same page anymore! There's absolutely no way for server to say if you have refreshed the current tab or opened the page in new.Disgrace
M
1

Also make sure your implementing Serializable on your ViewScoped beans, just as you would with a SessionScoped bean.

Marigolde answered 18/3, 2011 at 2:31 Comment(1)
Yes, and don't forget to set private static final long serialVersionUID = xxxx; to a project-wide-unique and including all your custom JARs serial number to your bean.Despairing

© 2022 - 2024 — McMap. All rights reserved.