Problema com EntityManager e Generics

Problema muito estranho ocorrendo. Estou usando JPA como API de persistência e Java 5.

Tenho uma classe com um método de busca definido assim:

public <T extends BaseEntity> T find(Class<T> clazz, Serializable pk) { try { return em.find(clazz, pk); } catch (RuntimeException e) { throw new BaseException(e); } }

Porém o código acima não compila (ao menos no JDeveloper 10.1.3.2-4066). Ocorre a seguinte mensagem de erro:

Ele diz que não encontra o método find no EntityManager, porém, segundo a documentação da API ele é definido assim:

No entanto, se eu mudo de <T extends …> de BaseEntity para Object na assinatura do método, ele compila:

public &lt;T extends Object&gt; T find(Class&lt;T&gt; clazz, Serializable pk) { try { return em.find(clazz, pk); } catch (RuntimeException e) { throw new BaseException(e); } }

Não entendo porque funciona com Object e não funciona com a minha interface BaseEntity.

Porém, eu acabei mudando o código como abaixo e funciona:

public &lt;T extends BaseEntity&gt; T find(Class clazz, Serializable pk) { try { return (T) em.find(clazz, pk); } catch (RuntimeException e) { throw new BaseException(e); } }

Retirei o <T> do primeiro argumento e faço um cast do retorno do método em.find().

Alguém tem idéia do porquê???

Você já achou tudo.

o grande problema é que seu IDE lhe traiu com a mensagem de erro.
por exemplo fiz o mesmo código que você aqui e o erro que me traz é “can not convert T to T”

você tem que lembrar que quando rodar seus generics serão trocados por "Classes reais"
então vamos fazer o que você fez sem generics, ficaria assim

public BaseEntity  find(Class clazz, Serializable pk) {   
    try {   
        return em.find(clazz, pk);   // esse metodo retorna um Object logo precisa de um cast, afinal o mais generico aceita o mais
                                               // especifico, o contrario não
    } catch (RuntimeException e) {   
        throw new BaseException(e);   
    }   
}  

então tudo que precisava era do Cast.

acho que o unico problema foi seu IDE que lhe pregou uma peça

Mesmo se eu fizer assim, não rola:

public &lt;T extends BaseEntity&gt; T find(Class clazz, Serializable pk) { try { return (T) em.find(clazz, pk); } catch (RuntimeException e) { throw new BaseException(e); } }

Acontece, que eu defino que T é subclasse de BaseEntity, logo, ele pode receber qualquer filho dela e retorná-lo.

Eu estou enganado?

então aqui funcionou normalmente, só colocando o cast.

você está certo, deve aceitar qualquer filho de BaseEntity

você pode mandar a declaração da sua classe?

faz um teste, tenta compilar esse projeto com o bom e velho javac do console :smiley:
só para averiguar se é o IDE

javac? Muitas dependências de biblotecas… Deixa pra lá.
Talvez eu tente no Eclipse depois.

[quote=danieldestro]javac? Muitas dependências de biblotecas… Deixa pra lá.
Talvez eu tente no Eclipse depois.[/quote]

hahaha meio chato mesmo eu nem lebro como usa direito (pobre escravo de IDE que sou)

mas eu fiz no eclipse mesmo

mesmo assim manda a declaração da sua classe
e se testar no eclipse e funcar, avisa ae para eu nunca usar o JDeveloper