[RESOLVIDO] Arquitetura e atualização de dados EJB x Managed Bean Session Scoped

4 respostas
B

Bom dia pessoal!

Estou com um problema que não consigo resolver. Deve ter uma explicação simples para isso, mas ainda não encontrei saídas para o caso. Segue:

Arquitetura
- Tenho 2 Entitys (Acao e Sistema) com relacionamento muitos para um (um sistema tem muitas acoes, cada acao é executada para unicamente um sistema)
- Tenho 2 Facades que executam operaçãos de criar, editar e excluir (AcaoFacade e SistemaFacade). Eles são EJBs que recebem o EntityManager por injeção de dependência
- Tenho 2 Controller (AcaoController e SistemaController). Eles são ManagedBeans que delegam para os Facades as operações em banco de dados.
- Tenho 2 CRUDS (Create Upate Destroy) (um para Acao e outro para Sistema) (gerados no padrão do Netbeans 6.9) (create.xhtml edit.xhtml view.xhtml e list.xhtml)

Problema:
- Dado que o cadastro de uma Acao atualiza o banco de dados e é corretamente visualizada pelo List.xhtml de seu Crud, por que não consigo visualizar a ação que já está no banco de dados pelo List.xhtml do CRUD do Sistema? O List.xhtml executa o getItems() de seu MB que invoca o findAll de seu EJB. As tecnologias usadas são JSF2 e JPA 2.0.

Entity
@Entity
@Table(name = "ACAO", catalog = "dbintegracoes", schema = "")
public class Acao {
    @Id
    @Basic(optional = false)
    @Column(name = "id", nullable = false)
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

     ...

    @ManyToOne
    @JoinColumn(name = "cd_sistema")
    private SistemaIntegrado sistema;
    private String descricao;
@Entity
@Table(name = "SISTEMAINTEGRADO", catalog = "dbintegracoes", schema = "")
public class SistemaIntegrado implements Serializable {

    public static final int ROTINA_PRELIMINAR_RETORNADA = 103;
    @Id
    @Basic(optional = false)
    @Column(name = "id", nullable = false)
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;
   
    ...   

    @OneToMany(targetEntity = Acao.class, mappedBy = "sistema", fetch = FetchType.EAGER)
    private Collection acaoCollection;

Facade (EJB)

public abstract class AbstractFacade<T> {
    private Class<T> entityClass;

    public AbstractFacade(Class<T> entityClass) {
        this.entityClass = entityClass;
    }

    protected abstract EntityManager getEntityManager();

    public void create(T entity) {
        getEntityManager().persist(entity);
        getEntityManager().flush();
    }
@Stateless
public class AcaoFacade extends AbstractFacade<Acao> {

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

    protected EntityManager getEntityManager() {
        return em;
    }

    public AcaoFacade() {
        super(Acao.class);
    }

    @Override
    public List<Acao> findAll() { // Ordenado por ordem alfabética

        CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
        javax.persistence.criteria.CriteriaQuery cq = cb.createQuery(Acao.class);
        Root<Acao> sistema = cq.from(Acao.class);
        cq.select(sistema);
        cq.orderBy(cb.desc(sistema.get("dtAcao")));

        return getEntityManager().createQuery(cq).getResultList();

    }
@Stateless
public class SistemaIntegradoFacade extends AbstractFacade<SistemaIntegrado> {
    @PersistenceContext(unitName = "IntegradorMPCTPU")
    private EntityManager em;

    protected EntityManager getEntityManager() {
        return em;
    }

    public SistemaIntegradoFacade() {
        super(SistemaIntegrado.class);
    }

      @Override
    public List<SistemaIntegrado> findAll() { 

        CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
        javax.persistence.criteria.CriteriaQuery cq = cb.createQuery(SistemaIntegrado.class);
        Root<SistemaIntegrado> sistema = cq.from(SistemaIntegrado.class);
        cq.select(sistema);
        cq.orderBy(cb.asc(sistema.get("nome")));

        return getEntityManager().createQuery(cq).getResultList();

    }

Controller (Managed Bean)

@ManagedBean(name = "acaoController")
@SessionScoped
public class AcaoController {

    private Acao current;
    private DataModel items = null;
    @EJB
    private br.gov.serpro.integrador.bean.AcaoFacade ejbFacade;

    public DataModel getItems() {
//        if (items == null) {
        items = getPagination().createPageDataModel();
//        }
        return items;
    }

public PaginationHelper getPagination() {
        if (pagination == null) {
            pagination = new PaginationHelper(9999999) {

                @Override
                public int getItemsCount() {
                    return getFacade().count();
                }

                @Override
                public DataModel createPageDataModel() {
                    return new ListDataModel(getFacade().findRange(new int[]{getPageFirstItem(), getPageFirstItem() + getPageSize()}));
                }
            };
        }
        return pagination;
    }

 public String create() {
        try {

            Calendar calendar = Calendar.getInstance();
            calendar.setTime(new Date());
            current.setDtAcao(calendar.getTime());// Define data atual
            if (current.getDtProximoPasso() != null) {
                calendar.setTime(current.getDtProximoPasso());
                calendar.add(Calendar.DAY_OF_MONTH, 1);
                current.setDtProximoPasso(calendar.getTime());
            }


            // Se necessidade foi escolhida, vale o sistema da necessidade escolhida
            if(current.getNecessidade()!= null){
                current.setSistema(current.getNecessidade().getSistemaIntegrado());
            }
            

            getFacade().create(current);

            JsfUtil.addSuccessMessage(ResourceBundle.getBundle("/Bundle").getString("AcaoCreated"));
            return prepareCreate();
        } catch (Exception e) {
            JsfUtil.addErrorMessage(e, ResourceBundle.getBundle("/Bundle").getString("PersistenceErrorOccured"));
            return null;
        }
    }
@ManagedBean(name = "sistemaIntegradoController")
@SessionScoped
public class SistemaIntegradoController {

    private SistemaIntegrado current;
    private DataModel items = null;
    @EJB
    private br.gov.serpro.integrador.bean.SistemaIntegradoFacade ejbFacade;

    public DataModel getItems() {
//        if (items == null) {
        items = getPagination().createPageDataModel();
//        }
        return items;
    }

public PaginationHelper getPagination() {
        if (pagination == null) {
            pagination = new PaginationHelper(9999999) {

                @Override
                public int getItemsCount() {
                    return getFacade().count();
                }

                @Override
                public DataModel createPageDataModel() {
                    return new ListDataModel(getFacade().findRange(new int[]{getPageFirstItem(), getPageFirstItem() + getPageSize()}));
                }
            };
        }
        return pagination;
    }

4 Respostas

R

Já debugou esse método getItems()?
A ação cadastrada é trazida?

B

Boa tarde raf4ever!

Debuguei sim. E olhei no banco de dados também. Pelo debug ele recupera o Sistema sem a nova ação (mesmo com a ação estando corretamente cadastrada no banco).

Fiquei pensando se não poderia ter alguma relação com cada EJB receber seu EntityManager por injeção de dependência.

Não sei se é possível, mas a impressão que passa é que a injeção trabalha com vários contextos de EntityManager, fazendo com que as Entity entrem em estados não sincronizados.

O interessante é que quando eu recompilo a aplicação e faço um re-deploy, tudo se sincroniza. O que acha?

B

Resolvido pessoal!

O problema era que o AbstractFacade não fazia commit. Quando eu fazia um re-deploy o jpa comitava para mim antes de instalar os novos entitys no container. Preciso pensar em como seria a melhor forma de dar esse commit, pois comitar nos métodos do AbstractFacade prejudicará as transações de toda a aplicação. Mas este já seria um problema a parte. Obrigado pela ajuda!

A

Por que você não usa transação distribuída pelo container (JTA) ? Aí você não precisa se preocupar com o commit e pode configurar suas transações com anotações nos métodos.

Criado 3 de setembro de 2010
Ultima resposta 6 de out. de 2010
Respostas 4
Participantes 3