2 Replies Latest reply on Nov 24, 2006 2:55 PM by Valtoni Boaventura

    Persist and Seam Managed Lifecycle

    Valtoni Boaventura Newbie

      Hello!
      I´m a newbie, but with some direction.
      I´m trying to do persistence with EJB3 injected EntityManager by annotation @PersistenceContext, but appear witch this EntityManager close the session all time that a call is made in page, because after the first call (all good occurs), in the second call, this appear:
      "org.hibernate.PersistentObjectException: detached entity passed to persist: br.com.bdh.view.seam.entity.FuncionarioEntity".

      I put all code from the registration seam example and the code of EJB appear well simpler then mine.

      My ejb:

      import static org.jboss.seam.ScopeType.EVENT;
      import java.util.List;
      
      import javax.annotation.Resource;
      import javax.ejb.Remove;
      import javax.ejb.SessionContext;
      import javax.ejb.Stateful;
      import javax.persistence.EntityManager;
      import javax.persistence.PersistenceContext;
      
      import org.hibernate.validator.InvalidValue;
      import org.jboss.seam.annotations.Destroy;
      import org.jboss.seam.annotations.Factory;
      import org.jboss.seam.annotations.In;
      import org.jboss.seam.annotations.Logger;
      import org.jboss.seam.annotations.Name;
      import org.jboss.seam.annotations.Out;
      import org.jboss.seam.annotations.Scope;
      import org.jboss.seam.annotations.datamodel.DataModel;
      import org.jboss.seam.annotations.datamodel.DataModelSelection;
      import org.jboss.seam.core.FacesMessages;
      import org.jboss.seam.log.Log;
      
      import br.com.bdh.view.seam.ejb.Funcionario;
      import br.com.bdh.view.seam.entity.FuncionarioEntity;
      
      @Stateful
      @Scope(EVENT)
      @Name("cadastrofuncionario")
      public class FuncionarioBean
       implements Funcionario {
      
       @DataModel
       private List<FuncionarioEntity> listaFuncionarios;
      
       @In(create = true)
       private FuncionarioEntity funcionario;
      
       @Out(required = false)
       @DataModelSelection
       private FuncionarioEntity funcionarioDaLista;
      
       @PersistenceContext
       private EntityManager em;
      
       @In(create=true)
       private transient FacesMessages facesMessages;
      
       @Logger
       private Log log;
      
       private boolean isExists(FuncionarioEntity funcionario) {
       return em.createQuery("from FuncionarioEntity f where f.nome = :nome")
       .setParameter("nome", funcionario.getNome())
       .getResultList().size() > 0;
       }
      
       public String criar() {
       log.info("Tentativa de input de funcionário.");
       if (em.contains(funcionario)) {
       facesMessages.add("O funcionário #{funcionario.nome} já está cadastrado");
       return null;
       }
       else {
       try {
       log.info("Funcionário a persistir: " + funcionario);
       if (isExists(funcionario)) {
       facesMessages.add("Este funcionário já existe. Não pode ser cadastrado novamente");
       }
       else {
       //funcionario = em.merge(funcionario);
       em.persist(funcionario);
       //em.flush();
       log.info("Novo funcionário #{funcionario.nome} cadastrado com sucesso");
       facesMessages.add("O funcionário #{funcionario.nome} foi cadastrado com sucesso");
       }
       } catch (org.hibernate.validator.InvalidStateException e) {
       InvalidValue[] vals = e.getInvalidValues();
       String message = "Estados inválidos: ";
       for (InvalidValue val: vals) {
       message += "- " + val + "\n";
       }
       facesMessages.add(message);
       return "/cadastroFuncionario.jsp";
       } catch (RuntimeException e) {
       ctx.setRollbackOnly();
       facesMessages.add("Erro: " + e.getMessage());
       }
       return "/cadastroFuncionario.jsp";
       }
       }
      
       @Factory("listaFuncionarios")
       public void findFuncionarios() {
       listaFuncionarios = em.createQuery("from FuncionarioEntity f order by f.nome desc")
       .setMaxResults(100)
       .getResultList();
       log.debug("Lista de funcionários obtida: " + listaFuncionarios.size());
       }
      
       @Destroy @Remove
       public void destroy() {
       listaFuncionarios = null;
       }
      
      }
      


      PS.: When i remove the comment of
      //funcionario = em.merge(funcionario);
      it´s works perfectly. But in the examples this was not necessary... I don´t know the reason!!!

      PS2.: I try to do @Transient field in entity and when his trying to read field "diasTrabalhados", the error "org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: br.com.bdh.view.seam.entity.FuncionarioEntity.diasTrabalhados, no session or session was closed" appear.

      The code of entity:

      import static org.jboss.seam.ScopeType.SESSION;
      
      import java.io.Serializable;
      import java.util.List;
      
      import javax.persistence.Column;
      import javax.persistence.Entity;
      import javax.persistence.GeneratedValue;
      import javax.persistence.GenerationType;
      import javax.persistence.Id;
      import javax.persistence.OneToMany;
      import javax.persistence.OrderBy;
      import javax.persistence.Table;
      import javax.persistence.Transient;
      
      import org.hibernate.validator.Length;
      import org.hibernate.validator.NotNull;
      import org.jboss.seam.annotations.Name;
      import org.jboss.seam.annotations.Scope;
      
      @Entity
      @Name("funcionario")
      @Scope(SESSION)
      @Table(name = "FUNCIONARIO")
      public class FuncionarioEntity implements Serializable {
      
       private static final long serialVersionUID = -7360165347366125305L;
      
       @Id
       @GeneratedValue(strategy = GenerationType.SEQUENCE)
       @Column(name="IDFUNCIONARIO")
       private int id;
       @NotNull @Length(min=10, max=100)
       private String nome;
       @OneToMany(mappedBy="funcionario")
       @OrderBy("data desc")
       private List<DiaUtilEntity> diasTrabalhados;
      
       @Transient
       public int getHorasTrabalhadas() {
       if (diasTrabalhados == null) {
       return 0;
       }
       else {
       return diasTrabalhados.size();
       }
       //return 0;
       }
      
       public FuncionarioEntity() {
      
       }
      
       public FuncionarioEntity(int id, String nome) {
       this.id = id;
       this.nome = nome;
       }
      
       public int getId() {
       return id;
       }
      
       public void setId(int id) {
       this.id = id;
       }
      
       public String getNome() {
       return nome;
       }
      
       public void setNome(String nome) {
       this.nome = nome;
       }
      
       public List<DiaUtilEntity> getDiasTrabalhados() {
       return diasTrabalhados;
       }
      
       public void setDiasTrabalhados(List<DiaUtilEntity> diasTrabalhados) {
       this.diasTrabalhados = diasTrabalhados;
       }
      
       public String toString() {
       int noDiasTrabalhados = 0;
       if (getDiasTrabalhados() != null) {
       noDiasTrabalhados = getDiasTrabalhados().size();
       }
       return "Id: " + id + " nome: " + nome + " dias trabalhados: " + noDiasTrabalhados;
       }
      
      }