VRaptor problemas com interfaces

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:

como vc sabe que é o Um ou o Dois?

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.

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.

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.

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.

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.

funciona sim, basta ter uma instancia para cada pessoa…

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

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)?

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.

Através de um converter certo?

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

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.