Home > OS >  cdi bean lack of value when accessed through public field
cdi bean lack of value when accessed through public field

Time:05-07

I have a configuration class, which I inject into another class.

Configuration class looks as follows:

@RequestScoped
public class Configuration {

    @ConfigProperty(name = "VALUE")
    public String value;

    public String getValue() {
        return value;
    }
}

This configuration is injected into the following place:

@ApplicationScoped
public class EndpointImpl implements Endpoint {

    private Configuration configuration;

    @Inject
    public EndpointImpl(Configuration configuration) {
        this.configuration = configuration;
        System.out.println("configuration.value="   configuration.value);
        System.out.println("configuration.getValue()="   configuration.getValue());
        System.out.println("configuration.value="   configuration.value);
    }

Logs printed after going through constructor:

configuration.value=null

configuration.getValue()=someValue

configuration.value=null

I added postConstructor with the below similar code:

@PostConstruct
public void postConstruct(){
    System.out.println("configuration.value=" configuration.value);
    System.out.println("configuration.getValue()=" configuration.getValue());
    System.out.println("configuration.value=" configuration.value);
}

and the result is the same.

Everything works fine as long as the value is retrieved through the getter method. When I try to retrieve it through the public field it returns null. I thought that, when CDI completes the process of building the bean, the fields inside the class will be set to appropriate values.

Why does it behave in such a way?

CodePudding user response:

This is expected, because your Configuration bean is @RequestScoped. The request scope is one of so-called normal scopes, and whenever you @Inject a normal-scoped bean, you will always get a so-called client proxy.

The client proxy exists to lookup the correct bean instance and forward method invocations to it. In this case, it will lookup the bean instance for current request.

So, when you're accessing fields, you're accessing them on the client proxy -- not on the instance that pertains to the current request.

Whenever you inject a normal-scoped bean, never access fields directly. Always call methods. You may access fields directly on @Singleton and @Dependent beans, because they don't come up with a client proxy.

  • Related