Question

I have (in a minimalistic version) the following CDI managed beans in 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");
        }
    }
}

And the following code to test this (Don't question why. It's only for this showcase.):

@Inject
Outer outer;

@Inject
Outer.Inner inner;

public void test() {
    inner.addFoo();
    outer.printValues();
}

I get an output of:

Values: {}

where I would have expected the value foo.

Further investigation revealed that the call to private void addValue accesses a version of the values attribute that lives in a Weld-generated Proxy of Outer whereas the call to public void printValues accesses the real attribute of the real managed bean instance.

To make things even more confusing: If I change the access level of addValue to one of package, protected or public everything works as expected.

But the purpose of the inner class in my case was to facilitate the method to be private so that other CDI clients of Outer can't call the method. And now thats the only thing that doesn't work :D

Any idea what's wrong? Is this a bug in Weld?

Was it helpful?

Solution

Currently all CDI providers use proxies (it isn't required by the spec, but that's how all three impls have been done) for injecting any non pseudo-scoped objects. If Outer was @DependantScoped I'm pretty sure it would work the way you want it to. The proxies created are naturally subclasses of your classes, so calling a private method on an injected object isn't going to work. Honestly I'm surprised it doesn't blow up.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top