Erro no acesso privado da classe externa injetada CDI da classe interna estática
-
21-12-2019 - |
Pergunta
Eu tenho (em uma versão minimalista) os seguintes beans gerenciados CDI no JBoss EAP 6.0.1
@ApplicationScoped
public class Outer {
private final List<String> values = new ArrayList<String>();
public void printValues() {
System.out.println("Values: " + values);
}
private void addValue(String value) {
values.add(value);
}
public static class Inner {
@Inject
private Outer outer;
public void addFoo() {
outer.addValue("foo");
}
}
}
E o código a seguir para testar isso (não questione o porquê.É apenas para esta vitrine.):
@Inject
Outer outer;
@Inject
Outer.Inner inner;
public void test() {
inner.addFoo();
outer.printValues();
}
Eu recebo uma saída de:
Values: {}
onde eu esperava o valor foo.
Uma investigação mais aprofundada revelou que a chamada para private void addValue
acessa uma versão do values
atributo que reside em um proxy gerado pelo Weld de Outer
enquanto o chamado para public void printValues
acessa o atributo real da instância real do bean gerenciado.
Para tornar as coisas ainda mais confusas:Se eu alterar o nível de acesso de addValue
para um dos package
, protected
ou public
tudo funciona como esperado.
Mas o objetivo da classe interna no meu caso era facilitar que o método fosse privado para que outros clientes CDI do Outer não pudessem chamar o método.E agora essa é a única coisa que não funciona :D
Alguma ideia do que há de errado?Isso é um bug no Weld?
Solução
Atualmente, todos os provedores de CDI usam proxies (não é exigido pelas especificações, mas é assim que todos os três impls foram feitos) para injetar quaisquer objetos sem pseudo-escopo.Se Exterior fosse @DependantScoped
Tenho certeza de que funcionaria do jeito que você deseja.Os proxies criados são naturalmente subclasses de suas classes, portanto, chamar um método privado em um objeto injetado não funcionará.Honestamente, estou surpreso que não exploda.