Welcome toVigges Developer Community-Open, Learning,Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
937 views
in Technique[技术] by (71.8m points)

jsf 2 - JSF does not populate @Named @RequestScoped bean with submitted input values

this is my first question in this beautiful site. I have googled a lot but I didn't find any solution.

I'm new to JSF and I'm learning it with "JSF 2 APIs and JBoss Seam" by Kent Ka lok Tong.

Now I have a problem with a simple login implementation. I have a login page:

<?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:h="http://java.sun.com/jsf/html">
    <h:head>
        <title>Login</title>
    </h:head>
    <h:body>
        <h1>Login</h1>
        <h:messages for="loginForm" />
        <h:form id="loginForm">
            <h:inputText id="username" value="#{loginRequest.username}" required="true" />
            <h:inputSecret id="password" value="#{loginRequest.password}" required="true" />
            <h:commandButton value="Login" action="#{loginRequest.doLogin}"></h:commandButton>
        </h:form>

    </h:body>
</html>

and a backing bean:

package app.controller;

import app.model.beans.User;
import javax.faces.bean.RequestScoped;
import javax.inject.Named;


@Named("loginRequest")
@RequestScoped
public class LoginRequest {

    private String username;
    private String password;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public LoginRequest(){
    System.out.println("created " + this.toString());
    }

    public String doLogin(){

        if(this.username != null && this.password != null){

            if(this.username.equals("user") && this.password.equals("password")){
            //this.userHolder.setCurrentUser(username);
            return "success";

            }
        return "failure";

        }
        return "failure";

    }


}

When I run the application my username and password properties result null. I debugged my app and I saw that setters methods are properly invoked. The problem is that when the setUsername is called there is and instance of the LoginRequest and when it's called the setPassword function the instance is different! Seems that the application do this:

obj1 = new LoginRequest() //username and password = null;
obj1.username = username;

obj1 = new LoginRequest() //username and password = null;
obj1.password = password;

obj1 = new LoginRequest() //username and password = null;
obj1.doLogin();

Where I'm in trouble? Where is the mistake?

Thanks a lot!

Best regards

Marco

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

From your bean:

import javax.faces.bean.RequestScoped;
import javax.inject.Named;

@Named("loginRequest")
@RequestScoped
public class LoginRequest {

You're mixing CDI and JSF annotations. You can and should not do that. Use the one or the other. I don't know what's the book is telling you, but most likely you have chosen the wrong autocomplete suggestion during the import of the @RequestScoped annotation. Please pay attention to if whatever the IDE suggests you matches whatever the book tells you.

So, you should be using either CDI annotations only

import javax.enterprise.context.RequestScoped;
import javax.inject.Named;

@Named("loginRequest")
@RequestScoped
public class LoginRequest {

or JSF annotations only

import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;

@ManagedBean(name="loginRequest")
@RequestScoped
public class LoginRequest {

Otherwise the scope defaults to "none" and every single EL expression referring the bean would create a brand new and separate instance of the bean. With three EL expressions referring to #{loginRequest} you would end up with 3 instances. One where name is been set, one where password is been set and one where action is been invoked.


Unrelated to the concrete problem, the managed bean name already defaults to the classname with 1st character lowercased conform Javabean specification. You could just omit the ("loginRequest") part altogether.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to Vigges Developer Community for programmer and developer-Open, Learning and Share
...