SessionScoped控制器无法正常工作

时间:2013-01-14 13:12:39

标签: jsf session java-ee javabeans

编辑: 好的,所以我尝试设置一些console.writes来检查发生了什么......似乎我的注销脚本在导航时被调用。但除了我的退出按钮外,我不会把它叫到任何地方。

这是我的模板代码:

<div class="navbar">
    <div class="navbar-inner">
        <ul class="nav">
            <li class="active"><a href="#{root}index.xhtml">Home</a></li>
            <li><a href="#{root}races/list.xhtml">Races</a></li>
            <li><a href="#{root}horses/list.xhtml">Horses</a></li>
            <h:panelGroup rendered="#{memberController.logged == true}">
                <li><a href="#{root}profile/history.xhtml">History</a></li>
                <li><a href="#" onclick="#{memberController.logout()}">Logout</a></li>
            </h:panelGroup>
            <h:panelGroup rendered="#{memberController.logged == false}">
                <li><a href="#{root}users/login.xhtml">Login</a></li>
                <li><a href="#{root}users/register.xhtml">Create Account</a></li>
            </h:panelGroup>
        </ul>
    </div>
</div>

原始讯息:

我正在为我的学校项目(Java EE)创建一个网站......这是我们这样做的第一年。 现在,因为这是晚上学校,只有一个学期学习它,你可能会发现我的做事方式并不是最好的:)

所以要开始,我正在尝试创建一个登录功能,但是我们可能会使用简单会话作用域成员对象而不是那些强大的安全代码行。

所以在这里你有几个课程:

会员类:

@Entity
@Table(name = "members")
public class Member implements Serializable {
    //+ Getters, setters, HashCode and equals

    @Id
    @GeneratedValue(strategy = GenerationType.TABLE)
    private long id;
    private double money;

    @NotNull(message = "Username cannot be null")
    @Size(min = 4, message = "Username should be of minimum 4 characters")
    private String userName;

    @NotNull(message = "Password cannot be null")
    @Size(min = 4, message = "Password should be of minimum 4 characters")
    private String password;

    @PostPersist
    private void initDefault() {
        this.money = 500;
    }
}

MemberBean类:

@Stateless
public class MemberBean {

    @PersistenceContext(unitName="HorseRacingPU")
    private EntityManager em;

    public Member getMember(long id){
        return em.find(Member.class, id);
    }

    public Member getMember(String username, String password){
        TypedQuery<Member> q = em.createQuery("SELECT u FROM Member u WHERE u.userName=?1 AND u.password=?2", Member.class);
        q.setParameter(1, username);
        q.setParameter(2, password);
        return q.getSingleResult();
    }

    public List<Member> getAllMembers(){
        TypedQuery<Member> q = em.createQuery("SELECT u FROM Member u", Member.class);
        return q.getResultList();
    }

    public Member addOrUpdateMember(Member u){
        Member original = em.find(Member.class, u.getId());
        if(original == null){
            em.persist(u);
            return u;
        }else{
            return em.merge(u);
        }
    }

    public Member deleteMember(long id){
        Member original = em.find(Member.class, id);
        if(original != null){
            em.remove(original);
        }
        return original;
    }
}

MemberController类:

@SessionScoped
public class MemberController implements Serializable {

    @EJB
    private MemberBean bean;
    private String username;
    private String password;
    private Member member;
    private boolean logged = false;
// + their getters and setters

    public List<Member> getAllMembers() {
        return bean.getAllMembers();
    }

    public String login() {
        member = bean.getMember(username, password);
        if (member != null) {
            logged = true;
            return "/races/list.xhtml?faces-redirect=true";
        }
        return "/users/login.xhtml?faces-redirect=true";
    }

    public String logout() {
        FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
        return "/index.xhtml?faces-redirect=true";
    }

    public void checkLogin(ComponentSystemEvent e) {
        if (!logged) {
            FacesContext context = FacesContext.getCurrentInstance();
            ConfigurableNavigationHandler handler = (ConfigurableNavigationHandler) context.getApplication().getNavigationHandler();
            handler.performNavigation("/users/login.xhtml?faces-redirect=true");
        }
    }

    public Member getMember() {
        return member;
    }

    public void submit() {
        bean.addOrUpdateMember(member);
    }
}

我得到的主要错误如下:

  

INFO:尝试重置响应时处理错误时出现异常。

可在此处找到更具体的详细信息错误:http://pastebin.com/h5nTNnes

所以当我登录时,一切都很好。我导航到另一个网址的那一刻(在转发到/ races / list之后)我得到注销。当我使用checkLogin()时错误本身显示:

<f:event type="preRenderView" listener="#{memberController.checkLogin}" />

我不确定这是否相关,但是当我在没有任何演示数据(或凭证错误)的情况下登录时,我得到一个评估异常,并且无法检索任何实体。 更多细节:http://pastebin.com/Tv9mQ1K9

这可能是什么?我现在挠了头3天,似乎无处可寻。

1 个答案:

答案 0 :(得分:1)

此,

<li><a href="#" onclick="#{memberController.logout()}">Logout</a></li>

不对。

onclick属性应引用JavaScript处理程序。例如。 alert('peek-a-boo');。 JSF / EL将其视为普通的字符串,并期望logout()方法返回一些JavaScript代码String,然后在HTML结果中将其内联。想象一下,该方法实际返回alert('peek-a-boo');,然后最终结果(正如您在浏览器中通过右键单击,查看源)将是:

<li><a href="#" onclick="alert('peek-a-boo');">Logout</a></li>

但是,在您的特定情况下,您实际上正在执行注销并返回字符串值/index.xhtml?faces-redirect=true。因此生成的HTML最终成为

<li><a href="#" onclick="/index.xhtml?faces-redirect=true">Logout</a></li>

哪个是无效的JS代码。但这不是主要问题:用户已经注销而没有点击链接!

您需要一个完整的JSF命令组件。例如。 <h:commandLink>

<li><h:form><h:commandLink value="Logout" action="#{memberController.logout()}"/></h:form></li>

这种方法只有在实际点击链接时才会调用,这正是您所需要的。