不调用@Named bean的@PostConstruct方法

时间:2014-02-15 23:05:41

标签: jsf cdi postconstruct

我正在尝试使用JPA和JSF实现简单列表和编辑页面,但是尽管数据库中有4条记录,但列表不返回任何行。堆栈跟踪中没有错误,因此我很难找到根本原因。这一次,我可以告诉我们没有调用init方法。你们能帮我一把吗?

Usuario.java

package br.com.jpajsf.model.entity;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity
public class Usuario {

@Id
@GeneratedValue
private int idUsuario;

private String dsIdentificador;

private String dsSenha;

private String dsSal;

private String dsNome;

private String dtNascimento;
// getters, setters, hashCode e equals.

UsuarioServices.java

package br.com.jpajsf.persistence;

import java.util.List;

import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import br.com.jpajsf.model.entity.Usuario;

@Stateless
public class UsuarioServices {
@PersistenceContext
private EntityManager em;

public List<Usuario> getUsuarios() {
    return em.createQuery("select u from Usuario u", Usuario.class)
            .getResultList();
}

public Usuario find(String id) {
    return em.find(Usuario.class, Integer.parseInt(id));
}

public void persist(Usuario u) {
    em.persist(u);
}
}

UsuarioBean.java

package br.com.jpajsf.domain;

import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import javax.inject.Inject;
import javax.inject.Named;

import br.com.jpajsf.model.entity.Usuario;
import br.com.jpajsf.persistence.UsuarioServices;

@ViewScoped
@Named
public class UsuarioBean {
@Inject
private UsuarioServices usuarioServices;

private Usuario usuario;
private List<Usuario> usuarios;

@PostConstruct
public void init() {
    Map<String, String> params = FacesContext.getCurrentInstance()
            .getExternalContext().getRequestParameterMap();

    if (!params.isEmpty()) {
        try {
            usuario = usuarioServices.find(params.get("idUsuario"));
        } catch (NumberFormatException e) {
        }
    }

    if (usuario == null) {
        usuario = new Usuario();
    }

    setUsuarios();
}

public List<Usuario> getUsuarios() {
    if (usuarios == null) {
        setUsuarios();
    }
    return usuarios;
}

public void setUsuarios() {
    this.usuarios = usuarioServices.getUsuarios();
}

public Usuario getUsuario() {
    return usuario;
}

public void setUsuario(Usuario usuario) {
    this.usuario = usuario;
}

public String salvar(Usuario u) {
    usuarioServices.persist(u);
    return "listar";
}
}

listar.xhtml

<h:head>
    <title>Cadastro de usuários</title>
</h:head>
<h:body>
    <h:form>
        <h:dataTable value="#{usuarioBean.usuarios}" var="usuario" border="1">
            <h:column>
                <f:facet name="header">ID</f:facet>
                #{usuario.idUsuario}
            </h:column>
            <h:column>
                <f:facet name="header">Email</f:facet>
                #{usuario.dsIdentificador}
            </h:column>
            <h:column>
                <f:facet name="header">Senha</f:facet>
                #{usuario.dsSenha}
            </h:column>
            <h:column>
                <f:facet name="header">Sal</f:facet>
                #{usuario.dsSal}
            </h:column>
            <h:column>
                <f:facet name="header">Nome</f:facet>
                #{usuario.dsNome}
            </h:column>
            <h:column>
                <f:facet name="header">Data Nascimento</f:facet>
                #{usuario.dtNascimento}
            </h:column>
            <h:column>
                <f:facet name="header">Opções</f:facet>
                <h:commandLink value="editar" action="editar?faces-redirect=true&amp;includeViewParams=true">
                    <f:setPropertyActionListener target="#{usuarioBean.usuario.idUsuario}" value="#{usuario.idUsuario}"/>
                </h:commandLink>
            </h:column>
        </h:dataTable>
    </h:form>
</h:body>
</html>

谢谢!

2 个答案:

答案 0 :(得分:2)

鉴于您的项目是Java EE6项目。要激活CDI bean,您希望在类路径上拥有文件beans.xml。 @Named only函数是在JSP / JSF页面中为EL提供可访问的CDI bean。 CDI bean符合条件的范围是:

  • javax.enterprise.context.RequestScoped;
  • javax.enterprise.context.ConversationScoped;
  • javax.enterprise.context.SessionScoped;
  • javax.enterprise.context.ApplicationScoped;
  • javax.enterprise.context.Dependent;如果指定了non,则为默认值。

为了保持一致,您希望坚持上述范围之一。请在下面找到JSR-299规范的引用 - 第58页 - 。它描述了最适合JSF框架的范围

  

对话上下文由内置钝化范围类型@ConversationScoped的内置上下文对象提供。会话范围在任何JSF面或非面部请求的所有标准生命周期阶段都处于活动状态。

     

会话上下文提供对与特定会话相关联的状态的访问。每个JSF请求都有一个关联的对话。容器根据以下规则自动管理此关联:

     
      
  • 任何JSF请求都只有一个关联对话。
  •   
  • 与JSF请求关联的会话在还原视图阶段开始时确定,并且在请求期间不会更改。
  •   

长话短说:

确保您的beans.xml位于类路径上后,请将您的ViewScoped替换为javax.enterprise.context.ConversationScoped。

编辑:

我忘了提到钝化。实际上,您的代码只接受“javax.enterprise.context.RequestScoped”,这可以用于演示目的。另一方面,ConversationScoped和SessionScoped bean都需要将Serializable实现为具有钝化能力。因此,对于您的代码是ConversationScoped,bean UsuarioBean及其所有成员属性也必须实现Serializable。

答案 1 :(得分:1)

我看到你的代码有一个错误。 @Named与

一起使用
import javax.faces.view.ViewScoped;

而不是

import javax.faces.bean.ViewScoped;

用于@ManagedBean