1

I'm trying to implement simple list and edit pages using JPA and JSF, but the list returns no lines despite the 4 records in the database. There are no errors in the stacktrace, therefore I'm having a rough time to find the root cause. For once, I can tell that the init method is not being called. Can you guys give me a hand?

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>

Thanks already!

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
user3278532
  • 11
  • 1
  • 2

2 Answers2

2

Given that your project is a Java EE6 one. To activate CDI beans you want to have the file beans.xml on your classpath. @Named only function is to make a CDI bean accessible for EL in your JSP/JSF pages. CDI beans eligible scopes are:

  • javax.enterprise.context.RequestScoped;
  • javax.enterprise.context.ConversationScoped;
  • javax.enterprise.context.SessionScoped;
  • javax.enterprise.context.ApplicationScoped;
  • javax.enterprise.context.Dependent; which is the default if non is specified.

To be consistent you want to stick to one of the above scopes. Please find below a quote of the JSR-299 specifications - page 58 -. It describes the scope which best fits JSF framework

The conversation context is provided by a built-in context object for the built-in passivating scope type @ConversationScoped. The conversation scope is active during all standard lifecycle phases of any JSF faces or non-faces request.

The conversation context provides access to state associated with a particular conversation. Every JSF request has an associated conversation. This association is managed automatically by the container according to the following rules:

  • Any JSF request has exactly one associated conversation.
  • The conversation associated with a JSF request is determined at the beginning of the restore view phase and does not change during the request.

Long story short:

After making sure your beans.xml is on the classpath, please replace your ViewScoped with javax.enterprise.context.ConversationScoped.

Edit:

I forgot to mention passivation. In fact, your code as it stands only accepts "javax.enterprise.context.RequestScoped" which is OK for demonstration purposes. On the other hand, both ConversationScoped and SessionScoped beans require to implement Serializable to be passivation-capable. Thus for your code to be ConversationScoped the bean UsuarioBean and all its member properties must implement Serializable as well.

Community
  • 1
  • 1
Sym-Sym
  • 3,578
  • 1
  • 29
  • 30
1

I saw one mistake on your code. The @Named is used with

import javax.faces.view.ViewScoped;

and NOT

import javax.faces.bean.ViewScoped;

which is used for @ManagedBean

  • Hi Alex. I'm using JBoss AS and it only supports JEE6, so no javax.faces.view.ViewScoped... – user3278532 Feb 15 '14 at 23:58
  • Then you should move to @ManagedBean – Alex Dutescu Feb 16 '14 at 00:04
  • I changed it to @RequestScoped with import javax.enterprise.context.RequestScoped and got the exact same results... – user3278532 Feb 16 '14 at 00:04
  • I have no experience with jsf and java6, but try some of the "old" ways of doing things in jsf. Named -> ManagedBean, use your old import for ViewScoped and Inject -> Ejb . If this doesn't help, maybe BalusC will, he is a jsf guru, and i'm his greatest fan :)) – Alex Dutescu Feb 16 '14 at 00:21
  • Yes. I might fallback to ManagedBean, but I wanted to push a little further with Named (even if I have to give up using the view scope). – user3278532 Feb 16 '14 at 01:50
  • 1
    @user3278532 in Java EE 6, you cannot mix `@ViewScoped` with CDI beans. You can add MyFaces CODI which adds `@ViewScoped` annotation. – Luiggi Mendoza Feb 16 '14 at 01:53