ejb3+jpa+json

7 respostas
M

Pessoal, estou usando EJB3+JSON e estou com um problema para listar valores. Tenho uma classe Usuario que tem referência para outra classe Usuario-Salario. O relacionamento entre as classes é de um para muitos, ou seja, cada usuário pode ter um ou mais usuarios-salário. Então na classe Usuario, tenho um set de usuarios-salário.

Na tela de usuários existe a necessidade da listagem de valores que estão contidos em UsuarioSalario, então imaginei retornar uma listagem de objetos de usuário com a referência da sua listagem de usuariosSalarios(usando uma namedQuery por exemplo). No entanto, esses valores não estão sendo retornados na view.

A lista de objetos de UsuarioSalario já está anotada como podem ver abaixo e mesmo assim a lista não é convertida pelo Json. Eu debugei as classes de conversão do Json e percebi que o problema poderia ser no tipo da listagem que estava sendo usada (Set ) , pois durante a conversão ele a identificava como IndirectSet o que não combina com os tipos que o Json converte (Collection, Array e Primitivo). O mesmo acontece se for usado List (Ele identifica como IndirectList). Tentei mudar o tipo da listagem para Array, mas descobri que o JPA não aceita esse tipo de mapeamento para objetos de entidades. Tentei usar ArrayList, mas tb ocorrem outros problemas.

Alguém já fez algo do tipo? Como contornou esse problema? Ou tem outra sugestão?

Action

public ActionForward listar(ActionMapping mapping,
                                ActionForm form,
                                HttpServletRequest request,
                                HttpServletResponse response) throws IOException, ServletException {

        Collection usuarios = usuarioEJBBean.listarTodos();

        JSONResponse jsonResponse = new JSONResponse();
        jsonResponse.put("usuarios", usuarios);
        jsonResponse.put("total", usuarios.size());

        String callback = request.getParameter("callback");
        request.setAttribute("json", jsonResponse.toJSON(callback, "BASICO, ADMINISTRATIVO", 3));
        return mapping.findForward("json");

    }

Bean

@Override public Collection listarTodos() { EntityManager em = emf.createEntityManager(); Query query = em.createNamedQuery("Usuario.findAll"); return query.getResultList(); }

Entidade Usuario

@Entity
@Table(name = "usuario")
@NamedQueries({
    @NamedQuery(name = "Usuario.findAll", query = "SELECT u FROM Usuario u")
                ?
})
@JSONObject
public class Usuario implements Serializable {
  private static final long serialVersionUID = 1L;

@OneToMany(mappedBy = "usuario")
@JSONAttribute(profile = "ADMINISTRATIVO")
private Set<UsuarioSalario> usuariosSalario;
...
public Set<UsuarioSalario> getUsuariosSalario() {
    return usuariosSalario;
}

public void setUsuariosSalario(Set<UsuarioSalario> usuariosSalario) {
    this.usuariosSalario = usuariosSalario;
}
}

Classe UsuarioSalario

@JSONObject
public class UsuarioSalario implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    @JSONAttribute(profile = "BASICO")
    private Integer id;

    @ManyToOne
    @JoinColumn(name = "usuario_id", referencedColumnName="id")
    @JSONAttribute(profile = "BASICO")
    private Usuario usuario;

?
}

7 Respostas

yorgan

Acho que o melhor é utilizar List mesmo.
Mas o que você pode fazer é inicializar a lista no seu Bean, assim o JPA vai carregar os dados antes de serializa-los.

Algo como:

@Override
    public Collection listarTodos() {
        EntityManager em = emf.createEntityManager();
        Query query = em.createNamedQuery("Usuario.findAll");
        
        Collection colecao = query.getResultList();
        Object objeto       = colecao.toArray()[0]; //pega o primeiro objeto da colecao
        Object property    = PropertyUtils.getProperty(entity, "usuariosSalario"); //pega o atributo usuariosSalario 
        if (Collection.class.isInstance(property)) {
                ((Collection) property).iterator(); //Inicializa a iteracao e faz o JPA carregar os dados.
        }
        return colecao;
    }

Para usar o PropertyUtils eu adicionei no classpath a lib commons-beanutils-1.8.2.jar

E se for o caso de sempre utilizar essas coleções, basta anota-la como Eager.

@OneToMany(mappedBy = "usuario" fetch=FetchType.EAGER) @JSONAttribute(profile = "ADMINISTRATIVO") private List<UsuarioSalario> usuariosSalario;

[]'s

Daniel

edysnipes

mila.c não vou poder ajudar a responder sua dúvida mais gostaria de saber qual a finalidade de você estar utilizando o JSON na sua aplicação? Estou estudando sobre o JSON e achei que ele serviria inicialmente para troca de informações entre sistemas.

Qual a finalidade dele na sua aplicação? E qual a implementação do JSON você está utilizando?

Espero não atrabalhar o tópico.

Agradeço!

yorgan

Olá edysnipes,
JSON é muito útil para requisições Ajax.
No meu blog eu tenho um post demonstrando a utilização dele com a ferramente ExtJS.
http://k2studio.com.br/site/2010/05/integracao-ext-js-com-vraptor3/

[]´s
Daniel

M

yorgan, obrigada pela sugestão mas este ainda não é o problema.

Se não me engano, sua sugestão somente faz com que a coleção de usuariosSalario seja carregada antes de serializar mas o problema é que no momento da conversão do objeto usuario para json ele não reconhece o tipo da coleção de usuariosSalarios entende? Ele acusa indirectSet… Mas ao debugar posso ver que o objeto usuario está completamente povoado, inclusive com o array de usuarioSalario. O json não consegue é converter essa lista para uma JSON string.

Esta conversão acontece através da chamada do método toJson na action linha 13 que é assim:

request.setAttribute("json", jsonResponse.toJSON(callback, "BASICO, ADMINISTRATIVO", 3));

Parece que agora consegui me explicar melhor…

yorgan

Qual o erro que ele retorna quando você utiliza List ao invés de Set?

M

Olha só… Ele não dá nenhum erro, ele não gera nenhuma exceção. Mas o problema é que internamente ele não identifica como uma coleção. Quando ele realiza os testes para identificar o tipo do atributo para converter para JSON, ele faz um object.getClass e o valor retornado desse método ao invés de ser ‘Collection’ é ‘Class’ e por isso a coleção é retornada nula.

Como expliquei anteriormente já tentei declarar como Set, List, ArrayList, Array, Vector, Collection… E a resposta é sempre a mesma… NULL!! :shock:

M

Alguém?

Criado 19 de agosto de 2010
Ultima resposta 9 de set. de 2010
Respostas 7
Participantes 4