facelets'目标无法访问'

时间:2012-07-09 03:00:19

标签: jsf-2 primefaces facelets cdi

我正在使用maven,jsf 2.0,java ee 6,jpa和glassfish。我有一个初始网页,询问您是否要登录或注册。如果他们说他们想要登录,他们会被转发到facelets / primefaces 3,这会显示一个包含用户名和密码文本框的登录页面。对于用户名文本字段,其值为

  

值= “#{authenticator.username}”

我得到了

  

“目标无法访问,标识符'身份验证者'已解析为空”

我正在使用beans.xml。我遵循了CDI bean的命名约定。 我在Authenticator构造函数中插入了一条日志消息,它似乎永远不会被调用,因为我没有收到消息。

另一个奇怪的是,一旦在蓝色的月亮中它起作用,我会得到如下内容:

  

07/08/2012 00:27:56.140 INFO ... Authenticator - 在Authenticator构造函数中

     

07/08/2012 00:27:56.171 INFO ... Authenticator - 获取Authenticator用户名

     

07/08/2012 00:27:56.171 INFO ... Authenticator - 在Authenticator构造函数中

     

07/08/2012 00:27:56.171 INFO ... Authenticator - 获取身份验证器密码

     

07/08/2012 00:27:56.171 INFO ... Authenticator - 在Authenticator构造函数中

     

07/08/2012 00:27:56.171 INFO ... Authenticator - 获取Authenticator用户名

     

07/08/2012 00:27:56.171 INFO ... Authenticator - 在Authenticator构造函数中

     

07/08/2012 00:27:56.171 INFO ... Authenticator - 获取身份验证器密码

     

07/08/2012 00:28:05.843 INFO ... Authenticator - 在Authenticator构造函数中

     

07/08/2012 00:28:05.843 INFO ... Authenticator - 在Authenticator构造函数中

     

07/08/2012 00:28:05.843 INFO ... Authenticator - 在Authenticator构造函数中

     

07/08/2012 00:28:05.843 INFO ... Authenticator - 获取身份验证器用户名

     

07/08/2012 00:28:05.843 INFO ... Authenticator - 在Authenticator构造函数中

     

07/08/2012 00:28:05.906 INFO ... Authenticator - 在Authenticator构造函数中

     

07/08/2012 00:28:05.906 INFO ... Authenticator - 获取身份验证器密码

     

07/08/2012 00:28:26.000 INFO ... Authenticator - 在Authenticator构造函数中

     

07/08/2012 00:28:26.000 INFO ... Authenticator - 在Authenticator构造函数中

     

07/08/2012 00:28:26.000 INFO ... Authenticator - 在Authenticator构造函数中

     

07/08/2012 00:28:26.031 INFO ... Authenticator - 在Authenticator构造函数中   07/08/2012 00:28:26.031 INFO ... Authenticator - 获取身份验证器密码

当它工作时,我不明白它为什么多次调用构造函数。

这是托管(cdi)bean:

package com.mlb.mybills.view.user;

import com.mlb.mybills.i18n.Messages;
import java.util.Locale;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ViewScoped;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.inject.Named;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Named("authenticator")
@ViewScoped
public class Authenticator
{
    private static final Logger log = LoggerFactory.getLogger(Authenticator.class);

    private String username;
    private char[] password;

    public Authenticator()
    {
      log.info("in Authenticator constructor");
    }

    public String getUsername()
    {
      log.info("getting Authenticator username");
        return username;
    }

    public void setUsername(String username)
    {
      log.info("getting Authenticator username");
        this.username = username;
    }

    public char[] getPassword()
    {
      log.info("getting Authenticator password");
        return password;
    }

    public void setPassword(char[] password)
    {
        log.info("setting Authenticator password");
      this.password = password;
    }

public void setPassword(String password)
    {
        log.info("setting Authenticator password");
      this.password = password.toCharArray();
    }


   public String authenticate()
    {
      log.info("in Authenticator.authenticate");
        String result = null;
        ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
        HttpServletRequest request = (HttpServletRequest) externalContext.getRequest();
        try
        {
            request.login(username, new String(password));
            //result = "/private/group.xhtml?faces-redirect=true";
         result = "/group.xhtml?faces-redirect=true";
        }
        catch (ServletException ex)
        {
            log.error("Failed to authenticate user.", ex);
            Locale locale = FacesContext.getCurrentInstance().getViewRoot().getLocale();
         FacesMessage facesMessage = new FacesMessage(FacesMessage.SEVERITY_ERROR, Messages.getString(
                    "Login.InvalidIdPasswordMessage", locale), null);
            FacesContext.getCurrentInstance().addMessage(null, facesMessage);
        }
      log.info("result=" + result);
        return result;
    }

    public String logout()
    {
        ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
        HttpServletRequest request = (HttpServletRequest) externalContext.getRequest();
        try
        {
            request.logout();
        }
        catch (ServletException servletEx)
        {
            log.warn("Failed to logout the user", servletEx);
        }
        return "/Login.xhtml?faces-redirect=true";
    }
}

3 个答案:

答案 0 :(得分:1)

您正在混合bean管理API。 @Named来自CDI,但@ViewScoped来自JSF。您需要使用一个或另一个,而不是两个都在一个支持bean上。现在,bean基本上由CDI管理,没有任何有效的范围,因此每次解析EL表达式#{authenticator}时都会构造bean。

要解决此问题,如果您打算坚持使用CDI,请使用@ConversationScoped代替@ViewScoped

@Named
@ConversationScoped

或者如果您打算坚持使用JSF,请使用@ManagedBean代替@Named

@ManagedBean
@ViewScoped

CDI方法的唯一缺点是你要@Inject Conversation作为一个属性,然后自己开始和结束它。

答案 1 :(得分:1)

你有一点问题,因为你正在混合CDI(@Named)和JSF(@ViewScoped)注释。由于这次比赛,它可能被召唤了很多次。您可以查看Seam Faces,MyFaces CODI或滚动您自己的ViewScoped for CDI版本,或放弃CDI并直接使用JSF。

答案 2 :(得分:0)

我找到了一个解决方案,虽然我不明白。我在以下链接中找到了它:a link!我还在faces-config.xml

中添加了以下条目,而不仅仅是放置@RequestScoped和@Named
<managed-bean>
   <managed-bean-name>authenticator</managed-bean-name>
   <managed-bean-class>com.mlb.mybills.view.user.Authenticator</managed-bean-class>
   <managed-bean-scope>session</managed-bean-scope>
</managed-bean>

有了这个,我不再遇到目标无法访问的错误。

显然我也纠正了BalusC指出的上述错误。谢谢大家。