VRaptor problemas com interfaces

12 respostas
M

Seguinte pessoal…

Já tentei adaptar algumas das soluções que achei no fórum mas todas sem sucesso :frowning:

Tenho um projeto organizado da seguinte forma:

projeto: módulo onde fica toda a lógica de negócio
projeto-web: cuida da apresentação utilizando o módulo “projeto”

Dentro do módulo projeto tenho as seguintes classes:

public interface Autor {

}

public class AutorUm implements Autor {

}

public class AutorDois implements Autor {

}

public class Documento {

    private Autor autor;

    public Autor getAutor() {
        return autor;
    }

    public void setAutor(Autor autor) {
        this.autor = autor;
    }

}

E no módulo responsável pela apresentação (projeto-web - onde se encontra o VRaptor) tenho o seguinte:

@Resource
public class DocumentoController {

    public void criarNovoDocumento(Documento documento) {
        //lógica...
    }

}

@Resource
public class Usuario {

    private String nome;
    private String senha;
    private Autor autor;

}

E por fim a JSP:

Autor: <input type="text" name="documento.usuario" value="usuario.autor"/>

Quando o usuário loga no sistema, ele pode ser um autor do tipo Um ou do tipo Dois.
O problema acontece justamente quando invoco o método criarNovoDocumento do Controller, lançando uma exception parecida com:

br.com.caelum.iogi.exceptions.InvalidTypeException: Cannot instantiate abstract type interface Autor

Trouxe aqui uma representação simplificada do contexto todo, mas minha duvida é a seguinte: por que o VRaptor está tentando instanciar a interface? Ele não deveria simplesmente pegar a instância de Documento (passada no método criarNovoDocumento) e chamar o setAutor passando o valor convertido do campo autor na JSP?

Já tentei usar um Converter e um ComponentFactory e até seguir os passos de alguns outros tópicos que encontrei aqui e nada até o momento.

O que eu estaria fazendo de errado?

Desde já obrigado. :wink:

12 Respostas

Lucas_Cavalcanti

como vc sabe que é o Um ou o Dois?

M

E ai Lucas, tudo certo?

Então cara, esse é só um projeto de estudo no qual estou experimentando várias coisas juntas, mas enfim… por enquanto o tipo de autor é settado durante o login mesmo, se o nome de usuário for usuarioum, por exemplo, uma instância de UsuarioUm é settada ao atributo autor da classe Usuario e assim também funciona para o UsuarioDois, mais ou menos assim:

@Resource
public class UsuarioController {
    @Post
	public void login(Usuario usuario) {
		if (usuario.getNome().equals("usuarioum")) {
			usuario.setAutor(new AutorUm());
		} else if (usuario.getNome().equals("usuariodois")) {
			usuario.setAutor(new AutorDois());
		}
        /*[...]*/
	}
}

E na hora de montar a JSP eu atribuo o autor do usuário logado ao value do campo da JSP.

Obrigado pela ajuda.

Lucas_Cavalcanti

meio estranho criar uma subclasse para cada usuário do sistema… já pensou em algo menos engessado?

essa informação deveria ficar na sessão do usuário, e não ser passada de form em form, isso é uma falha de segurança.

M

E ai Lucas…

Bem estranho mesmo essa estrutura, mas não consegui bolar uma outra forma de implementar isso ainda

Até pensei em settar o autor do documento no método criarNovoDocumento do Controller, mas também existe um caso em que um usuário logado não pode ser o autor de um documento, ao invés disso ele precisa selecionar um autor numa combo, que nesse caso seria exibida no lugar o input text

Se não fosse por esse caso, poderia colocar o usuário logado como autor do documento sem problemas, mas e nesse caso da combo?

Será que o design não está bem elaborado?

Obrigado.

Lucas_Cavalcanti

vc pode ter várias instancias de Autor, não precisa ser uma classe pra cada um…

se os autores estiverem num banco de dados, por exemplo, vc pode mostrar a lista dos autores nesse combo e selecioná-lo, pelo id.

M

Acho que entendi o que quiz dizer, mas nesse caso especifico cada implementação de autor representa uma entidade diferente no sistema, como por exemplo:

Digamos que AutorUm seja uma pessoa física e AutorDois um comitê formado por varias pessoas e que a interface Autor, implementada por ambas as classes, possua dois métodos getNome() e getAssinatura() que em AutorUm devolve apenas o nome da pessoa para ambos os métodos, mas que em AutorDois devolve o nome do comitê para o método getNome() e o nome de seus integrantes para o método getAssinatura().

Assim quando eu tiver um documento no qual o autor é do tipo AutorUm e os métodos documento.getAutor().getNome() e documento.getAutor().getAssinatura() forem respectivamente chamados o resultado seria algo como:
Autor: nome da pessoa
Assinatura: nome da pessoa

Já no caso de um documento com um autor do tipo dois:
Autor: comitê um
Assinatura: nome primeira pessoa
nome segunda pessoa
nome terceira pessoa
[…]

Ter apenas uma classe concreta para representar os autores ainda funcionaria nesse caso?
Realmente tentando explicar agora o processo pareceu meio estranho, vou ver se consigo repensar esse design, mas desde já muito obrigado pela ajuda e paciência.

Lucas_Cavalcanti

funciona sim, basta ter uma instancia para cada pessoa…

daí vc tem um atributo que seja o tipo do autor, caso seja necessário.

M

Poxa é verdade!!!

O que você disse Lucas faz todo sentido, não sei por que fiquei fissurado nas interfaces e não percebi isso ;-(

Mas só por curiosidade, o VRaptor sempre tentará instanciar um objeto para então settar seus atributos? Mesmo se eu passar um objeto inteiro (através de uma combo por exemplo)?

Lucas_Cavalcanti

não dá pra passar um objeto inteiro por uma combobox…

se vc der uma olhada no html gerado, do jeito que vc fez ele vai só fazer o toString do objeto no value das options…

o que a gente geralmente faz é usar como valor o id do objeto, e carregar o objeto do lado do servidor.

M

Através de um converter certo?

Lucas_Cavalcanti

não necessariamente…
vc faz:

<select name="autor.id">
   ...
   <option value="${autor.id}">${autor.nome}</option>
   ...
</select>

e se vc receber um Autor autor no método, ele vem com o id populado com o id do autor selecionado. Basta ter getters e setters

M

Firmeza… entendido ;-D

Vou refatorar as coisas aqui e continuar com os estudos.

Mais uma vez obrigado pela ajuda e desculpe se causei algum incomodo.

Obrigado.

Criado 5 de maio de 2013
Ultima resposta 8 de mai. de 2013
Respostas 12
Participantes 2