Maintain a session in Java with JSF and ManagedBean

Starting with Java EE and JSF, I need to create a simple login and keep the user id and nick in the session.

For that create a class

package Controlador;

import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;

@ManagedBean
@SessionScoped
public class SessionBean implements Serializable {

/**
 * 
 */
private static final long serialVersionUID = 1;

private int usuarioId;

private String usuarioNick;



public SessionBean() {
    super();
}...

From another class I try to save data in it, but when I try to access it returns Null pointer exception.

@ManagedBean
b@SessionScoped
public class UsuarioSessionBean {

@EJB
private UsuarioSessionDAO usuarioSession;

@ManagedProperty("#{sessionBean}")
private SessionBean sessionBean;

public void setSessionBean(SessionBean sb){
    if(sb != null){
        this.sessionBean = sb;
    }
}   
...

public String Login(){

    Usuario usr = usuarioSession.Login(usuario.getNick(),   usuario.getPass());
    if(usr != null){
        sessionBean.setUsuarioId(usr.getId());
        sessionBean.setUsuarioNick(usr.getNick());
        return "loginOk";
    }
    return "loginNo";
}

What am I doing wrong? or rather what would be the way to create a simple login?

 1
Author: Maske, 2016-05-06

3 answers

  1. It is much more recommended to use CDI-handled beans than JSF. Now, the use of @ManagedBean is not advised. Its replacement is @Named indicating that it is a CDI bean. It's important not to mix ManagedBeans with scopes CDI because it just won't work and you'll have run-time issues.

    import javax.inject.Named;
    import javax.enterprise.context.SessionScoped; // importante
    @Named
    @SessionScope
    public class SessionBean implements Serializable { ... }
    
  2. All classes that will be passivated (serialized and saved on the hard disk), as is the case of backing beans that have scopes ViewScoped, SessionScoped, FlowScoped, ConversationScoped, ApplicationScoped must be Serializable because CDI are serialized. Your class UsuarioSessionBean is not serializable.

    @Named
    @SessionScoped
    public class UsuarioSessionBean implements Serializable { ... }
    
  3. Choose the scope of your backing beans correctly. If you have many beans in session the application will lose performance, because in each response you send all those beans.

For example, you can create a utility class that allows you to get and add values to the session.

public class SessionUtils implements Serializable {

    public void add(String key, Object value) {
        FacesContext.getCurrentInstance().getSessionMap().put(key, value);
    }

    public void get(String key) {
        FacesContext.getCurrentInstance().getSessionMap().get(key);
    }
}

And you don't need UsuarioSessionBean, just a login controller that injects SessionUtils.

@Named
@RequestScoped
public class LoginBean {

   @Inject // inyectamos la dependencia
   private SessionUtils session;
   private String username;
   private String password;

   public String login() {
      // comprobar credenciales
      if(exito) {
          // añades el usuario a sesión
          sessionUtils.add("usuarioLogueado", usuario);
          return "home";
      }
      FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Acceso denegado", "Usuario o contraseña incorrecta");
      // como mensaje global
      FacesContext.getCurrentInstance().addMessage(null, message);
      return null; // retorna al mismo login
   }

   // getters y setters
}

Update

In the StackExchange Android App it appeared to me as "active", I have now seen the date and it is May. Sorry about the mess.

 2
Author: gugadev, 2016-06-13 14:08:10

I have done a login with the Google API Oauth2 is the same thing you want to do but instead of passing a session variables, you will have to pass two variables "login " and " password "

Login.xhtml

        <h:commandLink action="#{loginBean.sessGmail()}" ajax="false" type="submit">
            <h:graphicImage library="resources" name="images/iconGmailBlack.png" style="width: 150px; height: 150px; "/>
                                <f:param name="idParamtro" value="#{loginBean.Login}" />
                        </h:commandLink>

LoginBean.java

....
    private Session Login;

    public Session getLogin() {
        return Login;
    }

    public void setLogin(Session userLog) {
        this.userLog = Login;
    }
....

MainLogin.java

.....
@ManagedBean
@SessionScoped
public class MainBean {


    @ManagedProperty(value="#{loginBean}")
    private LoginBean userLogin;

    @PostConstruct
    public void init() {

            /** Se carga el Login en una variable de MainBean*/
            "variableMainBean" = userLogin.getLogin();
   ...}
...}

You also have to configure the application filters to not be able to access an application URL directly.

This is so that get an idea of the structure of calls to make the login. There are endless ways to do the login since you can put third-party APIs like the one I used to do the login, in addition to doing all kinds of checks with bbdd, etc.

If it helps you there are several tutorials on youtube to see directly the different ways you can do them.

 2
Author: Pablo García Tamarit, 2016-09-08 08:04:34

You must add it to the session map

ExternalContext context = FacesContext.getCurrentInstance ().getExternalContext(); context.getSessionMap().put (key,"")

 1
Author: Lobots, 2021-01-26 19:45:02