Атрибут "@inject" остается недействительным

Я пытаюсь ввести службу в свой bean, но всегда null. Я получаю следующую ошибку: WELD-001000 Ошибка разрешения свойства userBean против базового нуля.

Некоторые фрагменты кода:

index.xhtml

<h:body>
    Hello from Facelets
    #{userBean.name}
</h:body>

userbean.java

package beans;

import Domain.User;
import java.io.Serializable;
import javax.enterprise.context.SessionScoped;
import javax.inject.Inject;
import javax.inject.Named;
import service.UserService;

@Named
@SessionScoped
public class UserBean implements Serializable{
    @Inject UserService service;
    private User user;

    public UserBean(){
        this.user = service.find_user("foo");
    }

    public String getName(){
        return "bar";
    }
}

UserService.java

package service;

import Domain.User;
import javax.ejb.Stateless;
import javax.inject.Named;

@Named
@Stateless
public class UserService {
    public UserService(){}

    public User find_user(String name){
        return new User();
    }
}

Ответ 1

Сообщение об ошибке может быть подсказкой, что JVM не смог создать экземпляр UserBean. Ниже приведены некоторые предположения и должны быть доказаны:

Для Dependecy Injection требуется инжектор зависимости, инструмент, который вводит экземпляр UserService в UserBean. В коде вы уже используете этот инъецируемый экземпляр во время создания bean: вы вызываете введенную службу в конструкторе.

Если инжектор зависимостей запускает его работу после создания bean, тогда вызов службы внутри конструктора поднимет значение NullPointerException (потому что service все еще null в это время). Стоит проверить это, пытаясь на некоторое время уловить NPE в конструкторе UserBean. Если вы поймаете один - voilà - инжектор зависимостей начнет выполнение после создания bean и, как следствие, мы не сможем использовать внедренные службы во время создания экземпляра класса (= в конструкторе)


Идея обходного пути: реализовать вспомогательный класс поставщика услуг - внутренний класс может работать:

public class UserBean implements Serializable {
    static class UserServiceProvider {
      @Inject static UserService service;
    }

    // ... 

    public UserBean() {
      this.user = UserServiceProvider.service.findUser("kaas"); 
    }

    // ...
}

Неподтвержденный, но может работать - служба должна быть введена в класс поставщика, прежде чем использовать его в конструкторе beans.

Ответ 2

Другой альтернативой является использование аннотации метода @PostConstruct.

@SessionScoped
public class UserBean implements Serializable {
    @Inject UserService service;
    private User user;
    public UserBean() {

    }

   @PostConstruct
    void init(){
        this.user = service.findUser("kaas"); 
    }

  }

Прочитайте docs