Error en el acceso privado de la clase exterior inyectada de CDI de la clase interior estática
-
21-12-2019 - |
Pregunta
Tengo (en una versión minimalista) los siguientes frijoles administrados por CDI en 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");
}
}
}
y el siguiente código para probar esto (no cuestione por qué. Es solo para este escaparate):
@Inject
Outer outer;
@Inject
Outer.Inner inner;
public void test() {
inner.addFoo();
outer.printValues();
}
Recibo una salida de:
Values: {}
donde habría esperado el valor foo.
La investigación adicionalmente reveló que la llamada a private void addValue
accede a una versión del atributo values
que vive en un proxy generado por la soldadura de Outer
, mientras que la llamada a public void printValues
accede al atributo real de la instancia real de frijol administrado.
Para hacer las cosas aún más confusas: si cambio el nivel de acceso de addValue
a uno de package
, protected
o public
, todo funciona como se espera.
Pero el propósito de la clase interna en mi caso fue facilitar el método para ser privado para que otros clientes de CDI de los externos no puedan llamar al método. Y ahora eso es lo único que no funciona: D
¿Alguna idea de lo que está mal? ¿Es este un error en la soldadura?
Solución
Actualmente, todos los proveedores de CDI usan proxies (no es requerido por la especificación, pero así es como se han hecho las tres implings) para inyectar cualquier objeto no pseudo-alcance.Si el exterior era @DependantScoped
, estoy bastante seguro de que funcionaría como lo quieres.Los proxies creados son subclases naturales de sus clases, por lo que llamar a un método privado en un objeto inyectado no va a funcionar.Sinceramente, me sorprende que no vuelva a subir.