Open Session In View com Vraptor e Daos gerados pelo netbeans [Resolvido]

Olá e utenho as seguintes duvidas achei prático o criador de DAOs do netbeans, mas gostaria de saber como implemento o open session in view no Vraptor 3.
Sem modificar esses DAOs?? Mas se for pra modificar como eu faria? Ou esse DAO já tá protegido contra os problemas do lazy?

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package br.com.caelum.lojavirtual.dao;

import br.com.caelum.lojavirtual.dao.exceptions.NonexistentEntityException;
import br.com.caelum.lojavirtual.modelos.Produto;
import br.com.caelum.vraptor.ioc.Component;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import javax.persistence.EntityNotFoundException;

/**
 *
 * @author Marcos
 */
@Component
public class ProdutoJpaController {

    public ProdutoJpaController() {
        emf = Persistence.createEntityManagerFactory("default");
    }
    private EntityManagerFactory emf = null;

    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }

    public void create(Produto produto) {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            em.persist(produto);
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void edit(Produto produto) throws NonexistentEntityException, Exception {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            produto = em.merge(produto);
            em.getTransaction().commit();
        } catch (Exception ex) {
            String msg = ex.getLocalizedMessage();
            if (msg == null || msg.length() == 0) {
                Long id = produto.getId();
                if (findProduto(id) == null) {
                    throw new NonexistentEntityException("The produto with id " + id + " no longer exists.");
                }
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void destroy(Long id) throws NonexistentEntityException {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Produto produto;
            try {
                produto = em.getReference(Produto.class, id);
                produto.getId();
            } catch (EntityNotFoundException enfe) {
                throw new NonexistentEntityException("The produto with id " + id + " no longer exists.", enfe);
            }
            em.remove(produto);
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public List<Produto> findProdutoEntities() {
        return findProdutoEntities(true, -1, -1);
    }

    public List<Produto> findProdutoEntities(int maxResults, int firstResult) {
        return findProdutoEntities(false, maxResults, firstResult);
    }

    private List<Produto> findProdutoEntities(boolean all, int maxResults, int firstResult) {
        EntityManager em = getEntityManager();
        try {
            Query q = em.createQuery("select object(o) from Produto as o");
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }

    public Produto findProduto(Long id) {
        EntityManager em = getEntityManager();
        try {
            return em.find(Produto.class, id);
        } finally {
            em.close();
        }
    }

    public int getProdutoCount() {
        EntityManager em = getEntityManager();
        try {
            Query q = em.createQuery("select count(o) from Produto as o");
            return ((Long) q.getSingleResult()).intValue();
        } finally {
            em.close();
        }
    }

}

Na verdade você não vai precisar fazer uma OpenSessionInView porque o Vraptor já faz isso.

Basta você receber seu entity-mamager se você usa JPA ou sua Hibernate Session se você usa Hibernate puro. http://vraptor.caelum.com.br/documentacao/componentes-utilitarios-opcionais/

Voce só precisa adicionar no seu web.xml:

<context-param> <param-name>br.com.caelum.vraptor.provider</param-name> <param-value>br.com.caelum.vraptor.util.jpa.JPACustomProvider</param-value> </context-param>

Depois anotar sua dao como @Component e injetar a entity-manager via construtor da dao. Porém a sua entity-manager precisa se chamar default.

Mas tipo eu teria mexer nesse DAO, aí, não faria mais sentido o gerador de DAO’s do netbeans, porque iria dá muito trabalho ter que editar vários DAOs.
Então, vou ter que usar os generics para criar uma classe genérica.
Alguém dá uma luz de um DAO genérico preparada para o vraptor 3 utilizar…
Porque tentei criar um que era baseado em anotações do spring(para transações e injeção de dependências), mas compilava e tudo mas dava erros de null pointer…e até exclui já…=/
Alguém me ajuda a modifcar esse DAO acima para se tornar uma classe genérica pela qual herdarão os DAOs concretos.

se esse é o DAO que o netbeans gera, ele está errado… você não deve abrir a entityManagerFactory toda hora pq ela demora pra abrir, deve existir só uma aberta durante toda a aplicação…

de qqer forma, se vc usar o JPACustomProvider do vraptor, basta vc apagar as primeiras linhas e trocar por:

# @Component  
 public class ProdutoJpaController {  
     private EntityManager entityManager;   
     public ProdutoJpaController(EntityManager entityManager) {  
         this.entityManager = entityManager;
     }  
     private EntityManager getEntityManager() {  
         return this.entityManager;
     }
     //.... resto
}

muito provavelmente até dê pra mudar o template de geração de código do netbeans pra gerar isso ao inves do padrão…

[quote=Lucas Cavalcanti]se esse é o DAO que o netbeans gera, ele está errado… você não deve abrir a entityManagerFactory toda hora pq ela demora pra abrir, deve existir só uma aberta durante toda a aplicação…

de qqer forma, se vc usar o JPACustomProvider do vraptor, basta vc apagar as primeiras linhas e trocar por:

# @Component  
 public class ProdutoJpaController {  
     private EntityManager entityManager;   
     public ProdutoJpaController(EntityManager entityManager) {  
         this.entityManager = entityManager;
     }  
     private EntityManager getEntityManager() {  
         return this.entityManager;
     }
     //.... resto
}

muito provavelmente até dê pra mudar o template de geração de código do netbeans pra gerar isso ao inves do padrão…
[/quote]

Acabei de modificar ele aqui:
Coloquei o que você pediu e tirei os begin’s e commit’s…já q o vraptor já faz isso.
Agora quero transformá-lo em classe genérica… para fazer vários DAO’s só herdando desta classe.
Ficou legal o DAO??

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.caelum.lojavirtual.dao;

import br.com.caelum.lojavirtual.dao.exceptions.NonexistentEntityException;
import br.com.caelum.lojavirtual.modelos.Produto;
import br.com.caelum.vraptor.ioc.Component;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.persistence.EntityNotFoundException;

/**
 *
 * @author Marcos
 */
@Component
public class ProdutoJpaController {

    private EntityManager entityManager;

    public ProdutoJpaController(EntityManager entityManager) {
        this.entityManager = entityManager;
    }

    public EntityManager getEntityManager() {
        return this.entityManager;
    }

    public void setEntityManager(EntityManager entityManager) {
        this.entityManager = entityManager;
    }

    public void create(Produto produto) {
        EntityManager em = null;
        em = getEntityManager();
        em.persist(produto);
    }

    public void edit(Produto produto) throws NonexistentEntityException, Exception {
        EntityManager em = null;
        try {
            em = getEntityManager();
            produto = em.merge(produto);
        } catch (Exception ex) {
            String msg = ex.getLocalizedMessage();
            if (msg == null || msg.length() == 0) {
                Long id = produto.getId();
                if (findProduto(id) == null) {
                    throw new NonexistentEntityException("The produto with id " + id + " no longer exists.");
                }
            }
            throw ex;
        }
    }

    public void destroy(Long id) throws NonexistentEntityException {
        EntityManager em = null;
        em = getEntityManager();
        Produto produto;
        try {
            produto = em.getReference(Produto.class, id);
            produto.getId();
        } catch (EntityNotFoundException enfe) {
            throw new NonexistentEntityException("The produto with id " + id + " no longer exists.", enfe);
        }
        em.remove(produto);
    }

    public List<Produto> findProdutoEntities() {
        return findProdutoEntities(true, -1, -1);
    }

    public List<Produto> findProdutoEntities(int maxResults, int firstResult) {
        return findProdutoEntities(false, maxResults, firstResult);
    }

    private List<Produto> findProdutoEntities(boolean all, int maxResults, int firstResult) {
        EntityManager em = getEntityManager();
        Query q = em.createQuery("select object(o) from Produto as o");
        if (!all) {
            q.setMaxResults(maxResults);
            q.setFirstResult(firstResult);
        }
        return q.getResultList();
    }

    public Produto findProduto(Long id) {
        EntityManager em = getEntityManager();
        return em.find(Produto.class, id);
    }

    public int getProdutoCount() {
        EntityManager em = getEntityManager();
        Query q = em.createQuery("select count(o) from Produto as o");
        return ((Long) q.getSingleResult()).intValue();
    }
}

vc não precisa (nem deveria ter) do getter e setter pro entityManager… pode usar o campo direto, já que ele vem do construtor já direitinho pra vc…

-remova o getter e setter pra entityManager
-troque todos os acessos a entityManager pra this.entityManager (não precisa criar as variaveis locais)

sua classe já vai ficar beem mais limpa

qto a deixar genérica, não dá pra deixar os métodos findProdutoEntities e getProdutoCount genéricos de um jeito mto bonito…

[quote=Lucas Cavalcanti]vc não precisa (nem deveria ter) do getter e setter pro entityManager… pode usar o campo direto, já que ele vem do construtor já direitinho pra vc…

-remova o getter e setter pra entityManager
-troque todos os acessos a entityManager pra this.entityManager (não precisa criar as variaveis locais)

sua classe já vai ficar beem mais limpa

qto a deixar genérica, não dá pra deixar os métodos findProdutoEntities e getProdutoCount genéricos de um jeito mto bonito… [/quote]

Eu fiz uma modificação extrema aquilo era só pra ter uma idéia rsrs…
Esse aqui eu modifiquei e deixei o getEntityManager para casos especiais…mas…to tendo um problema com a classe genérica e a classe concreta…:

OBS.: Foi baseada em um exemplo de um livro de JSF, Spring e JPA…=X
Genérica

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.caelum.lojavirtual.dao;

import br.com.caelum.vraptor.ioc.Component;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;
import java.util.Map;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.Query;

/**
 *
 * @author Marcos
 */
@Component
public class JpaController<T, ID extends Serializable> {

    private EntityManager entityManager;
    private final Class<T> oClass;//object class

    public JpaController(EntityManager entityManager) {
        this.entityManager = entityManager;
        this.oClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
    }

    public Class<T> getObjectClass() {
        return this.oClass;
    }

    protected EntityManager getEntityManager() {
        if (entityManager == null) {
            throw new IllegalStateException("Erro");
        }
        return entityManager;
    }

    public T atualizar(T object) {
        getEntityManager().merge(object);

        return object;

    }

    public void excluir(T object) {
        object = getEntityManager().merge(object);
        getEntityManager().remove(object);
    }

    public T pesquisarPorId(ID id) {
        return (T) getEntityManager().find(oClass, id);
    }

    public T salvar(T object) {
        getEntityManager().clear();
        getEntityManager().persist(object);

        return object;
    }

    public List<T> todos() {
        String queryS = "SELECT obj FROM " + oClass.getSimpleName() + " obj";
        Query query = getEntityManager().createQuery(queryS);
        return query.getResultList();

    }

    public List<T> listPesqParam(String query, Map<String, Object> params) {
        Query q = getEntityManager().createQuery(query);
        for (String chave : params.keySet()) {
            q.setParameter(chave, params.get(chave));

        }
        return q.getResultList();
    }

    public List<T> listPesqParam(String query, Map<String, Object> params,
            int maximo, int atual) {
        Query q = getEntityManager().
                createQuery(query).
                setMaxResults(maximo).
                setFirstResult(atual);

        for (String chave : params.keySet()) {
            q.setParameter(chave, params.get(chave));

        }
        return q.getResultList();
    }

    public List<T> listPesq(String query) {
        Query q = getEntityManager().createQuery(query);
        return q.getResultList();
    }

    public T pesqParam(String query, Map<String, Object> params) {
        Query q = getEntityManager().createQuery(query);
        for (String chave : params.keySet()) {
            q.setParameter(chave, params.get(chave));

        }
        try {
            return (T) q.getSingleResult();
        } catch (NoResultException nre) {
            return null;
        }
    }
}

Concreta:

@Component
public class ProdutoJpaController extends JpaController<Produto, Long>{

}

Quando estou a editar e fazer o código acima da classe concreta, o corretor “ortográfico” do netbeans…rsrs pede um construtor sem argumentos na classe genérica … aí não entendi… pq já existe um construtor q vai receber o entity manager do Vraptor…vou ter q criar este outro…agora num sei como fica…as coisas…

construtores não são herdados em java… vc vai ter que criar um construtor em cada classe filha, recebendo um EntityManager e repassando pra classe mãe via super(manager);

E não é que funfou legal
kkkk Que ignorância minha…valeu, to parado em relação a Java desde o ano passado. =)
Obrigadão!!

Codigo da classe concreta:

@Component
public class ProdutoJpaController extends JpaController<Produto, Long>{

    public ProdutoJpaController(EntityManager entityManager) {
        super(entityManager);
    }


}

Resolvidooooo!!!

[quote=Mark0z]Olá e utenho as seguintes duvidas achei prático o criador de DAOs do netbeans, mas gostaria de saber como implemento o open session in view no Vraptor 3.
Sem modificar esses DAOs?? Mas se for pra modificar como eu faria? Ou esse DAO já tá protegido contra os problemas do lazy?
.
.
.
.
.
[/quote]

Acho legal vc usar esse recurso do Netbeans apenas para criar as classes de modelo pois com mais 3 classes (interceptador de transação + DAO generico + DaoFachada) vc resolve tudo isso !!!