EJB not injecting into Component (Vaadin CDI add-on)

I’m playing around with the Charts add-on at the moment and am trying to inject a mock data source into a Chart class. The data source is a singleton bean that has already had a reference injected into the View that will be displaying the chart but I was under the impression that this shouldn’t matter as singletons are application scoped.

The EJB is injected correctly into the view but when the chart class is instantiated, the injection of the data source fails and returns a null reference. I’ve been using the no-interface facility up until now but even if I do use an interface for the data source, this doesn’t make any difference. I’m guessing that there is either a scoping issue or I’m fundamentally misusing/misunderstanding CDI. The other possibility is that I’ve run into a limitation to the Vaadin CDI add-on as this methodology worked without problems in JSF2.2.

If anyone has any ideas or pointers I’d be really grateful as it’s pretty frustrating. Granted this is a quick and dirty implementation but it is a prototype; refactoring to separate concerns (data provision vs building UI components) may well sort the issue but I’d like to understand what’s happening here first.

EJB:

@Startup
@Singleton
public class MockDataProvider implements Serializable {
    private static final long serialVersionUID = -4789949304830373309L;
    private Random rand = new Random();
    private Collection<Person> people = new ArrayList<Person>();
    private Collection<Address> addresses = new ArrayList<Address>();
    private Collection<Evnt> evnts = new ArrayList<Evnt>();
    private Collection<TicketType> tickets = new ArrayList<TicketType>();


    /**
     * Initialize the data for the application
     */
    public MockDataProvider() {
    }

    @PostConstruct
    private void init() {
        loadAddressData();
        loadTicketData();
        loadEventData();
        loadPersonData();
    }

View class (injection works fine here)

@CDIView(DashboardView.VIEW_ID)
public class DashboardView extends AbstractMVPView implements IDashboardView {
    public final static String VIEW_ID = "dashboard";

    @Inject
    @CDILogger
    private Logger logger;

    @EJB
    MockDataProvider dataProvider;

    @Inject
    EventsPerMonthChart eventsPerMonthChart;

    private Table eventsTable;

    private Table peopleTable;

    public DashboardView() {
    }

Finally, the Chart class - injection fails here so calling dataProvider.getEvntCollection() throws a null pointer exception.

@UIScoped
public class EventsPerMonthChart extends Chart {

    @EJB
    MockDataProvider dataProvider;

    public EventsPerMonthChart() {
        super(ChartType.PIE);

        setCaption("Events per month");
        getConfiguration().setTitle("");
        getConfiguration().getChart().setType(ChartType.PIE);
        setWidth("100%");
        setHeight("90%");

        DataSeries series = new DataSeries();
        ArrayList<Evnt> events = (ArrayList) dataProvider.getEvntCollection();

OK - it looks like the problem was down to ignorance on my part as I did not understand the contexts where EJB injection is permitted.

The EJB (MockDataProvider) is instantiated by the container and injected into the DashboardView class which, as it was annotated with @CDIView, is also managed by the container. Hence, everything works fine. However, the Chart object was not container managed (despite my misguided addition of @Dependent to try and get the container to “notice” it) - injection into POJOs is not permitted but appears to fail silently which only added to my confusion.

Granted, the code structure is pretty appalling (close coupling, highly dependant and no separation of concerns) and this shoddy approach to prototyping has been responsible for creating the issue. Passing the Charts object the data directly or a via reference to the EJB via a constructor call works without problems.

Good job your learn from your mistakes. At the rate I’m making them, I’m going to be a genius!