Аннотированный тип @ManagedProperty возвращает null

#jsf-2 #ejb-3.0 #jpa-2.0 #glassfish-3

#jsf-2 #ejb-3.0 #jpa-2.0 #glassfish-3

Вопрос:

У меня есть этот служебный компонент:

 @Stateless
public class BookService
{
    @PersistenceContext(unitName="persistentUnit")
    protected EntityManager entityManager;

    public BookModel find(Long id) {
       return entityManager.find(BookModel.class, id);
    }
}
  

А вспомогательный компонент для страницы Facelet является:

 @ManagedBean(name = "bookBean")
@RequestScoped
public class BookBean implements Serializable
{
    @EJB
    private BookService bookService;

    @ManagedProperty(value="#{param.id}")
    private Long id;

    private DataModel<BookModel> books;
    private BookModel currentBook;

    @PostConstruct
    public void init() {
        if (id == null) {
           // UPDATE: Retrieve a list of books.
        } else { 
           // UPDATE: id shouldn't be null here.
           // Get detail info about a book using the id
           currentBook = bookService.find(id);
        }
    }

    public Long getId() {
       return id;
    } 

    public void setId(Long id) {
       this.id = id;
    } 

    public BookModel getCurrentBook() {
       return currentBook;
    }

    public void setCurrentBook(BookModel currentBook) {
       this.currentBook = currentBook;
    }
 }
  

Почему значение id всегда возвращает null, даже если URL-адрес возвращается как bookedit.jsf?id=5418 я этого не понимаю.

Кроме того, я нахожу EntityManager#find метод довольно ограничительным в том смысле, что он принимает только значение первичного ключа в качестве второго параметра. Что, если я хочу передать [хэшированное] значение вместо первичного ключа. Как я могу это сделать с помощью EntityManager#find метода?

PS Я замечаю, что EntityManager#find требование одинаково как для реализаций OpenJPA, так и для EclipseLink. Хм…

Комментарии:

1. Вы пытаетесь использовать введенное значение в @PostConstruct. Я не уверен, что произойдет первым — внедрение @ManagedProperty или @PostConstruct. Вы это проверили?

2. @Osw: @PostConstruct выполняется после внедрения всех зависимостей, так что эта часть в порядке.

3. @BalusC: Вы правы в соответствии с документацией по DI и @PostContruct . Тем не менее, я не уверен, почему я получаю null вместо 5148 . Это очень странно!

4. Код выглядит нормально. Скорее всего, это опечатка или какой-то недосмотр. Я бы начал отладку сопоставления параметров запроса внутри конструктора / postconstruct . Изучите ExternalContext#getRequestParameterMap() , чтобы увидеть, присутствует ли параметр.

5. Действительно ли возможно ссылаться на параметр с помощью #{param.id }? Разве вам не нужно привязать параметр к свойству managedbean и прочитать его оттуда?

Ответ №1:

Я только что попробовал это в одном из моих управляемых компонентов, и это работает. Вот соответствующий код, он в основном такой же, как у вас:

 @ManagedBean
@RequestScoped
public class TestBean {
    @ManagedProperty(value = "#{param.id}")
    private Long prop;

    @PostConstruct
    public void init() {
        System.out.println(prop);
        // prints 1234 if I go to the url with http://localhost/page.jsf?1234
    }

    public Long getProp() {
        return prop;
    }

    public void setProp(Long prop) {
        this.prop = prop;
    }
}
  

Я запускаю это на glassfish 3.1.1. Единственная мысль, которая у меня возникла, это, возможно, введенный EJB каким-то образом искажает область запроса в ManagedBean?