Extensão CDI, alterando o tipo processado
Pergunta
Utilizando Weld 1.1.13.Final em teste com Arquillian....
Digamos que eu injete algo volátil em um campo.Algo como uma propriedade sujeita a alterações que desejo que o bean proprietário do ponto de injeção receba eventos de alteração.Pensei em criar uma extensão CDI.
Capturamos o evento ProcessAnnotatedType e procuramos todos os campos que possuem uma anotação personalizada nos pontos de injeção de campo:
<T> void pat(@Observes ProcessAnnotatedType<T> event, BeanManager bm) {
final AnnotatedType<T> target = event.getAnnotatedType();
for (AnnotatedField<? super T> field : target.getFields())
if (field.isAnnotationPresent(Value.class)) { // ignore that I don't check @Inject here for the moment
CtClass wrapper = pool.get(target.getJavaClass().getName());
ConstPool cp = wrapper.getClassFile().getConstPool();
CtMethod m = CtNewMethod.make(....)
....
wrapper.addMethod(m);
event.setAnnotatedType(bm.createAnnotatedType(wrapper.toClass()));
}
}
Depois disso, ele pegou todos os pontos de injeção dos campos e substituiu o WeldField subjacente por um novo campo correspondente ao tipo "wrapper".Caso contrário, a validação do bean falhará.
Mas isso só funciona para configuração de coisas durante a inicialização, não quando, por exemplo, o Arquillian usa o Bean Manager para inicializar uma classe que injeta um dos meus "wraps".As coisas falham porque o Bean Resolver usa o Type como uma chave hash para encontrar beans.
Basicamente não creio que possa "mascarar" uma classe que é anotada (transformada em bean) pelo CDI com um método extra para receber eventos customizados.Teria sido legal, mas um tipo é um tipo (ou seja,não tenho ideia de como fazer proxy ou falsificar o equals/hashCode).
Solução
Entendi.Acontece que a função de valor de computação (extensão do Google) dentro do resolvedor TypeSafeBeanResolver (pelo menos a implementação do CDI Weld) é inteligente.Se eu apenas estender a classe:
CtClass wrapper = pool.makeClass(target.getJavaClass().getName()+"Proxy");
wrapper.setSuperclass(pool.get(target.getJavaClass().getName()));
.....
final AnnotatedType<T> other = bm.createAnnotatedType(wrapper
.toClass());
então tudo funciona bem.Testado a captura de um evento em um bean.Postará o código em um Gist com um comentário.