6
votes

Is constructor injection supported in GlassFish 3.1's implementation of CDI for managed beans? I have a @Singleton EJB into which I want to inject another managed bean (contained in the same EJB module) using constructor injection. Field injection does work. But with constructor injection I get a NullPointerException from AbstractSingletonContainer.

This does work:

@Singleton
public class FooBean implements Foo {

  @Inject private BarBean bar;

}

This does not work:

@Singleton
public class FooBean implements Foo {

    private final BarBean bar;

    @Inject
    public FooBean(BarBean bar) {
        this.bar = bar;
    }

}
2
What version of glassfish? If this was not with 3.0.1, give it a try.Pascal Thivent
I think figured it out. The example is actualy working. It does only crash if the ear is already deployed when glassfish starts. After redeploying it works. Seems like a GlassFish bug to me.Toni

2 Answers

9
votes

CDI does support direct field injection, initializer method parameter injection and constructor parameter injection. From the CDI 1.0 specification:

3.7. Bean constructors

When the container instantiates a bean class, it calls the bean constructor. The bean constructor is a constructor of the bean class.

The application may call bean constructors directly. However, if the application directly instantiates the bean, no parameters are passed to the constructor by the container; the returned object is not bound to any context; no dependencies are injected by the container; and the lifecycle of the new instance is not managed by the container.

3.7.1. Declaring a bean constructor

The bean constructor may be identified by annotating the constructor @Inject.

@SessionScoped
public class ShoppingCart implements Serializable {
    private User customer;

    @Inject
    public ShoppingCart(User customer) {
        this.customer = customer;
    }

    public ShoppingCart(ShoppingCart original) {
        this.customer = original.customer;
    }

    ShoppingCart() {}

    ...
}

@ConversationScoped
public class Order {
    private Product product;
    private User customer;

    @Inject
    public Order(@Selected Product product, User customer) {
        this.product = product;
        this.customer = customer;
    }

    public Order(Order original) {
        this.product = original.product;
        this.customer = original.customer;
    }

    Order() {}

    ...
}

If a bean class does not explicitly declare a constructor using @Inject, the constructor that accepts no parameters is the bean constructor.

If a bean class has more than one constructor annotated @Inject, the container automatically detects the problem and treats it as a definition error.

If a bean constructor has a parameter annotated @Disposes, or @Observes, the container automatically detects the problem and treats it as a definition error.

A bean constructor may have any number of parameters. All parameters of a bean constructor are injection points.

I wonder if your problem could be related to WELD-141 though.

References

3
votes

Constructor injection is supported in GlassFish 3.x but you must provide a default constructor anyway to satisfy EJB specs.

This will work:

@Singleton
public class FooBean implements Foo {

    private final BarBean bar;

    public FooBean() {
      this.bar = null;
    }

    @Inject
    public FooBean(BarBean bar) {
        this.bar = bar;
    } 
}

but Glassfish (this part is container dependant) will call the default constructor before the Injected one.