[RESOLVIDO] Problemas de Herança com JSF2/JPA

Olá Pessoal. Eu estou implementando uma arquitetura usando JEE 6 e, portanto, estou utilizando JSF 2.0.4 na ponta. Está tudo funcionando perfeitamente exceto pelo fato de que eu não consigo acessar um atributo herdado em uma entidade do JPA.

Tenho a entidade Usuario que herda da entidade Pessoa. Os meus Backbeans tem uma superclasse que possuem um atributo chamado entidade (o tipo desse atributo é passado utilizando Generics). No caso do exemplo, o tipo passado via Generics é Usuario. No meu xhtml, quando tento acessar algum atributo de Usuario que seja herdado de Pessoa (atributo ‘nome’ por exemplo), o mesmo aparece como valor ‘null’.

#{pessoaBean.entidade.nome} //Deveria retornar um valor, mas retorna null

E quando tento ‘escrever’ no atributo, no console aparece o erro “target=”#{pessoaBean.entidade.nome}": The class ‘foo.Usuario’ does not have a writable property ‘nome’.".

Percebi que mesmo colocando os atributos como ‘protected’ em Pessoa não resolvia o problema. O único jeito de fazer funcionar foi replicando os get/set dentro da entidade Usuario e marcando como @Transient pra não dar problema com o Hibernate. Só que não quero ter que fazer isso. Além do código ficar horroroso, teria redundância…

Pesquisei bastante na internet mas não encontrei uma solução. Alguém já passou por isso ou sabe como resolver?

Agradeço qualquer ajuda. Obrigado.

Ps.: Estou utilizando CDI (Weld) e JBoss AS 6

Eu uso de um jeito bem parecido, você tem essas anotações na classe pessoa ?:

@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) // ou outra, dependendo de sua estratégia @MappedSuperclass

Qual o tipo de mapeamento vc está utilizando ?

Single_Table, Joined_Table, TABLE_PER_CLASS ?

Posta seu código, que fica mais facil te ajudar.

abs,

Obrigado pessoal pelas respostas.

Bem… no meu caso a estratégia que melhor atende minha necessidade é a JOINED. Minhas classes estão assim:

Pessoa:

@Entity
@Inheritance(strategy=InheritanceType.JOINED)
@SequenceGenerator(name="pessoa_seq", sequenceName="pessoa_seq")
public class Pessoa extends Entidade {
	private static final long serialVersionUID = -3873597239233216513L;

	protected Integer identificador;
	protected String nome;

	public Pessoa() {}

	public Pessoa(String nome) {
		super();
		this.nome = nome;
	}

	@Id
	@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="pessoa_seq")
	public Integer getIdentificador() {
		return identificador;
	}
	public void setIdentificador(Integer identificador) {
		this.identificador = identificador;
	}

	@NotNull
	@Size(min=1, max=50)
	public String getNome() {
		return nome;
	}

	public void setNome(String nome) {
		this.nome = nome;
	}
}

Usuario:

@Entity
public class Usuario extends Pessoa {
	private static final long serialVersionUID = -4521766138720954608L;

	private String usuario;
	private String senha;

	public Usuario() {}

	public Usuario(String usuario, String senha) {
		super();
		this.usuario = usuario;
		this.senha = senha;
	}

	@NotNull
	@Size(min=3, max=20)
	public String getUsuario() {
		return usuario;
	}

	public void setUsuario(String usuario) {
		this.usuario = usuario;
	}

	@NotNull
	@Size(min=5, max=10)
	public String getSenha() {
		return senha;
	}

	public void setSenha(String senha) {
		this.senha = senha;
	}
}

Para fins de teste, eu substitui o JOINED por TABLE_PER_CLASS, mas deu o mesmo problema. Meu banco é gerado pelo próprio Hibernate, então não preciso definir o nome de tabelas e campos. Também testei configurando um @DiscriminatorColumn em Pessoa e um @DiscriminatorValue em Usuario, mas continuou o erro.

Alguém tem mas alguma idéia?

Desde já agradeço. Obrigado.

Não querendo insistir, mas tentou usar o
@MappedSuperclass ?

Encontrei a solução para o problema pessoal. Obviamente que o exemplo que eu usei não condiz exatamente com a realidade do meu projeto, portanto vou colocar a solução aqui de acordo com o exemplo. Não irá fazer muito sentido do ponto de vista do “negócio” do exemplo, mas vai esclarecer as causas e soluções.

O problema era que minha Superclasse de entidades (classe base de qual todas as entidades herdam) tinha um método abstrato, do qual não tinha me alertado antes:

O que acontecia é que por algum motivo obscuro o JSF não conseguia encontrar o atributo nome corretamente dentro de Usuario por causa desse método ai. As soluções são ou retirar o método “get” abstrato, ou acrescentar um par “set” abstrato de modo que fará com que o JSF “enxergue” corretamente o atributo dentro de Pessoa e Usuario.

public abstract Serializable getNome();

public abstract void setNome(Serializable nome);

Fazendo dessa forma funcionou corretamente, sem a necessidade de alterações nos mapeamentos das entidades.

Gostaria de agradecer aos colegas que me ajudaram. Muito obrigado!!!

É isso ai, qualquer dúvida estou a disposição.