2

我在我创建的这个示例 jsf 项目中遇到了这个问题。托管 bean 不会被实例化。豆类:

@ManagedBean(name="loginMB")
@RequestScoped
public class LoginMB extends AbstractMB {

    private static final long serialVersionUID = -8523135776442886000L;
    @ManagedProperty("#{userMB}")
    private UserMB userMB;

    //getters and setters 

   public String login() {      
        UserSupport userSupport = new UserSupportImpl();        
        User user = userSupport.isValidLogin(email, password);      
        if (user != null) {
            getUserMB().setUser(user);
            FacesContext context = FacesContext.getCurrentInstance();
            HttpServletRequest request = (HttpServletRequest) context
                    .getExternalContext().getRequest();
            request.getSession().setAttribute("user", user);
            return "loggedIn";
            //return "/pages/protected/index.xhtml";
        }
        displayErrorMessageToUser("Check your email/password");
        return null;
    }
}

ManagedBean 注解和 RequestScope 注解已从

导入 javax.faces.bean.*;

这就是我在上面使用 bean 的方式,

    <!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" 
xmlns:f="http://java.sun.com/jsf/core" 
xmlns:h="http://java.sun.com/jsf/html"
    xmlns:p="http://primefaces.org/ui">
<h:head>
</h:head>
<h:body>
    <p>#{bundle.loginHello}</p>
    <h:form>
        <p:growl showDetail="false" life="3000" />
        <h:panelGrid columns="2">
            <h:outputLabel value="#{bundle.loginUserName}" />
            <h:inputText value="#{loginMB.email}" label="Email" id="email" required="true">             
                <f:validateLength minimum="6" />
            </h:inputText>
            <h:outputLabel value="#{bundle.loginPassword}" />

            <h:inputSecret value="#{loginMB.password}" label="Password" id="senha" required="true" autocomplete="off" >         
                <f:validateLength minimum="6" />
            </h:inputSecret>


        </h:panelGrid>
        <p:commandButton action="#{loginMB.login}" value="Log in" ajax="false" />
    </h:form>
</h:body>
</html>

其他托管 bean

@SessionScoped
@ManagedBean(name = "userMB")
public class UserMB implements Serializable {
    public static final String INJECTION_NAME = "#{userMB}";
    private static final long serialVersionUID = 1L;

    private User user;
        .......
}

例外:

javax.el.PropertyNotFoundException: /login.xhtml @14,83 value="#{loginMB.email}": Target Unreachable, identifier 'loginMB' resolved to null
at com.sun.faces.facelets.el.TagValueExpression.getType(TagValueExpression.java:100)
at com.sun.faces.renderkit.html_basic.HtmlBasicInputRenderer.getConvertedValue(HtmlBasicInputRenderer.java:95)

面孔-config.xml

<faces-config
    xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_1.xsd"
    version="2.1">

    <application>
        <resource-bundle>
            <base-name>messages</base-name>
            <var>bundle</var>
        </resource-bundle>
        <message-bundle>messages</message-bundle>
    </application>

    <navigation-rule>
        <from-view-id>/login.xhtml</from-view-id>
        <navigation-case>
            <from-action>#{loginMB.login}</from-action>
            <from-outcome>loggedIn</from-outcome>
            <to-view-id>/index.xhtml</to-view-id>
            <redirect />
        </navigation-case>      
    </navigation-rule>
    <!-- <managed-bean>
        <managed-bean-name>loginMB</managed-bean-name>
        <managed-bean-class> com.sample.jsfjpa.beans.LoginMB</managed-bean-class>
        <managed-bean-scope>request</managed-bean-scope>
    </managed-bean>
    <managed-bean>
        <managed-bean-name>userMB</managed-bean-name>
        <managed-bean-class> com.sample.jsfjpa.beans.UserMB</managed-bean-class>
        <managed-bean-scope>session</managed-bean-scope>
    </managed-bean> -->
</faces-config>

在此处输入图像描述

4

1 回答 1

2

除非您专门调用它们的属性或方法之一,否则不会创建托管 bean。所有范围都会发生这种情况,除了@ApplicationScoped那些@ManagedBean(eager=true)在 JSF 上下文加载时专门创建的范围。

在这里,您是#{loginMB}从视图中引用的,但不是#{userMB}这样,因此没有机会创建它。

为了实例化您的@SessionScoped托管 bean,您可以在登录页面中添加以下代码:

<f:metadata>
    <f:event type="preRenderView" listener="#{userMB.initialize}" />
</f:metadata>

它设置了一个在页面渲染之前执行的监听器。您可以在这里只调用一个空方法(如果尚未创建,JSF 将构造您的 bean 来执行它)。

从 JSF 2.2 开始,您可以替换preRenderViewnew 的方法f:viewAction,这有一些好处(它是无参数的,并且不会在回发时被调用):

<f:metadata>
    <f:viewAction action="#{userMB.initialize}" />
</f:metadata>
于 2013-09-03T13:13:51.387 回答