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 =开发者_如何学Python 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
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.
精彩评论