Search code examples
jsfejbcdiomnifaces

Using a Stateful SessionScoped bean to store user login info in a JSF application


Good day

This issue has been resolved while creating a MCVE (thanks Kukeltje for making me do that :) )

See the answer posted below for a MCVE that works.

@SessionScoped
@Stateful
public class StoringUserInfo implements Serializable {

    private HashMap<String, String> userSettingMap;
    private String userName = "Test";

    public StoringUserInfo() {
        this.userSettingMap = new HashMap<>();
    }

    public void addSetting(String name, String setting) {
        userSettingMap.put(name, setting);
    }

    public String getSetting(String name) {
        return userSettingMap.get(name);
    }

    public HashMap<String, String> getUserSettingMap() {
        return userSettingMap;
    }

    public void setUserSettingMap(HashMap<String, String> userSettingMap) {
        this.userSettingMap = userSettingMap;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String projectName) {
        this.projectName = userName;
    }
}

Then for instance in one @ViewScoped @Named bean I want to do this:

@Named
@ViewScoped
public class NewProjectView implements Serializable {

    private static final long serialVersionUID = 1L;
    private String userName;
    @Inject private transient StoringUserInfo userInfo;

    public void submitForm(){
        userInfo.setUserName("NEW")
        // return to dashboard
        FacesContext.getCurrentInstance().getViewRoot().getViewMap().clear();
        PrimeFaces.current().ajax().update(":content", ":formHeader:mainMenu", ":formHeader:growl");
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

}

Then on another @ViewScoped @Named bean I want to retrieve the stored value as such (the try is suppress the error on app deployment due to the @PostConstruct getting nulls)

@Named
@ViewScoped
public class EditProjectView implements Serializable {

    private static final long serialVersionUID = 1L;
    private String userName;
    @Inject private transient StoringUserInfo userInfo;


    @PostConstruct
    public void init() {
        getValues()
    }

    private void getValues(){
    try {
        userName = userInfo.getUserName(); // this must display on form load
    } catch (Exception e) {
        e.printStackTrace();
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

}

The workflow inside the app ensures that the page that sets the values are visited before the page / pages that need the values. Debugging correctly shows this as well.

However, the @ViewScoped @Named beans always display null, they never reread the values from the @SesionScoped bean? What am I missing here?

Setting a default value to the userName String in the @SessionScoped @Stateful bean shows the name 'Test' on the second form.

However the updated value never gets read on form render / load. It thus seems that @PostConstruct only executes at app deployment time?

I also added this to my xhtml file:

<o:form id="editProjectForm">
        <f:metadata>
            <f:viewAction action="#{editProjectView.getProjectValues}"/>
            <p:ajax update="editProjectFieldSet"/>
        </f:metadata>
        <p:fieldset id="editProjectFieldSet" legend="#{editProjectView.userName}"/>

But it still does not re query the SessionScoped bean before render. It only shows the default init value of 'Test'


Solution

  • The main difference between the two versions are:

     1. Replaced <o:form> with <h:form> 
    

    Application is running on WildFly 14 with PrimeFaces 6.2.9 and OmniFaces 3.2