ti-enxame.com

Obtendo o erro de primavera "O bean chamado 'x' deve ser do tipo [y], mas era realmente do tipo [$ Proxy]" no Jenkins

Estou depurando isso há algum tempo agora, e espero que alguém possa lançar alguma luz aqui.

Eu tenho um projeto Maven que é adicionado ao Jenkins, usando o JDK 1.6. Estou usando o AOP neste projeto para lidar com a transação do banco de dados.

Quando executo a compilação no Jenkins, meu testcase falha com as seguintes exceções: -

Caused by: org.springframework.beans.factory.BeanCreationException: 
Error creating bean with name 'dataHandlerClassificationImpl': 
Injection of resource dependencies failed; nested exception is 
org.springframework.beans.factory.BeanNotOfRequiredTypeException: 
Bean named 'writerDataLocationImpl' must be of type [xxx.script.WriterData], 
but was actually of type [$Proxy17]
    ...
    ...
Caused by: org.springframework.beans.factory.BeanNotOfRequiredTypeException: 
Bean named 'writerDataLocationImpl' must be of type [xxx.script.WriterData], 
but was actually of type [$Proxy17]
    ...
    ...

A classe DataHandlerClassificationImpl se parece com isso: -

@Service
public class DataHandlerClassificationImpl extends DataHandler {

    @Resource(name="writerDataLocationImpl")
    private WriterData writerData;

    ...
}       

WriterData é uma interface com múltiplas implementações.

Eu sou capaz de executar o código sem problemas do IDE. Para determinar se é um problema do Maven ou do Jenkins, naveguei para a pasta de tarefas do projeto do Jenkins usando a linha de comando e sou capaz de executar mvn test sem erros.

Eu sei que o erro de proxy tem algo a ver com o AOP, e que eu só posso conectar automaticamente a uma interface em vez de uma classe concreta ... mas esse não é o caso aqui, pois sou capaz de executar meu código muito bem fora do Jenkins.

Alguma ideia? Obrigado.

19
limc

Trecho dos comentários da pergunta acima:

Você está executando o Cobertura, o Sonar ou outra ferramenta de instrumentação de código no Jenkins? Observe que mvn site também pode ser configurado para incluir o relatório Cobertura em site gerado.

O problema com o Cobertura é que ele executa uma instrumentação de código de bytes bastante pesada, incluindo a adição de algumas interfaces personalizadas. Quando o Spring é iniciado, ele gera proxies para beans. Se o bean tiver pelo menos uma interface, ele usará o proxy padrão Java. Caso contrário, ele tentará criar um proxy baseado em classe.

Acho que, no seu caso, o proxy da classe CGLIB foi usado, mas após a instrumentação Cobertura, a Primavera voltou a Java proxies. Isso causou erro de inicialização porque a injeção de dependência esperava a classe (ou subclasse CGLIB)).

Para encurtar a história, force os proxies da classe CGLIB e você ficará bem:

<aop:config proxy-target-class="true"/>
43
Tomasz Nurkiewicz