Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JSF 2.0 Injecting managed bean with a different scope

Tags:

jsf

jsf-2

I have a controller that is stateless which takes care of processing forms. This is defined as ApplicationScoped. On my page I have a form associated to a backing bean defined as a ViewScoped.

The error I got when I want to process the form:

serverError: class com.sun.faces.mgbean.ManagedBeanCreationException Unable to create managed bean myController.  The following problems were found:
     - The scope of the object referenced by expression #{myFormBean}, view, is shorter than the referring managed beans (myController) scope of application

In my form:

       Name: <h:inputText value="#{myFormBean.name}" id="name" />
        <h:commandButton value="Save Name" action="#{myController.processForm}">
            <f:ajax render="nameResult" />
        </h:commandButton>
       Your name is <h:outputText value="#{myFormBean.name}" id="nameResult"/>

The controller:

@ManagedBean
@ApplicationScoped
public class MyController {
    @ManagedProperty("#{myFormBean}")
    private MyFormBean myBean;
    public void processForm() {
        System.out.println(myBean.getName());
        // Save current name in session
        FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put(
                "name", myBean.getName());
    }
}

The backing bean:

@ManagedBean
@ViewScoped
public class MyFormBean {
    private String name;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

I could solve that by setting the controller as SessionScoped but it’s not a clean way since the controller is stateless, so I don’t need one controller for each session. One controller for the whole application should be sufficient.

I have a Spring MVC background, that’s why I am confused on how to do things with JSF 2.0

like image 239
Sydney Avatar asked Dec 09 '22 07:12

Sydney


1 Answers

There is a flaw in your design. Your controller is not stateless at all. It has a property which is different for each request/view, namely the myBean. If it was supported, then every new request/view would override the previously set one and the enduser will face the property value of a completely different enduser. This leads to problems in high concurrent situations.

You need to make it request/view scoped instead of application scoped. Still then, I believe that you have to approach it completely different. You're manually setting an attribute in the session scope in the action method instead of setting it as a property of an (injected) session scoped bean. How to solve it properly depends on the functional requirement which is not clear from the question.

like image 54
BalusC Avatar answered Feb 04 '23 02:02

BalusC