Почему PostConstruct не вызывается?

Я работаю над простым приложением Java EE.

У меня есть класс следующим образом:

import javax.annotation.PostConstruct;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

@Stateless
public class BlogEntryDao {

    EntityManager em;

    @PostConstruct
    public void initialize(){
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("Persistence");
        em = emf.createEntityManager();
    }

    public void addNewEntry(){
        Blogentry blogentry = new Blogentry();

        blogentry.setTitle("Test");
        blogentry.setContent("asdfasfas");

        em.persist(blogentry);

    }
}

Итак, мой управляемый bean вызывает этот метод. Пока здесь нет проблем. Но поскольку метод initialize не вызывается, я получаю NPE в em.persist.

Почему метод initialize не вызывается? Я запускаю это на сервере Glassfish.

С уважением.

Ответ 1

Аннотации Java EE bean, такие как @PostConstruct, применяются только к контейнерам beans. Если вы просто вызываете new BlogEntryDao самостоятельно, контейнер не собирается перехватывать создание и вызывает метод @PostConstruct.

(Кроме того, вам лучше использовать @PersistenceContext или @PersistenceUnit вместо ручной выборки EntityManagerFactory в вашем методе initialize(), и вы должны создать EntityManager для каждого вызова addNewEntry(), так как они недолговечны. Выполнение этих изменений полностью устранит необходимость initialize().)

Ответ 2

Поскольку этот вопрос сначала возникает в Google для "postconstruct not called", другая причина, по которой метод @PostConstruct не может быть вызван, кроме того, используя ключевое слово new вместо того, чтобы помещать @PostConstruct в Spring bean если у вас есть круговая зависимость.

Если этот bean должен был зависеть от другого bean, зависящего от этого bean, ваш другой bean мог бы вызвать addNewEntry() до инициализации BlogEntryDao, хотя BlogEntryDao является зависимостью для этого другого bean.

Это потому, что Spring не знал, какой bean вы хотите загрузить первым из-за круговой ссылки. В этом случае можно удалить циклическую ссылку или использовать параметры конструктора @AutoWired/@Value вместо значений элементов или сеттеров или, если вы используете конфигурацию xml, возможно, вы можете поменять порядок, в котором определены beans.

Ответ 3

У меня была такая же проблема в моем приложении. Вы не опубликовали свой XML файл конфигурации контекста bean (так что я не уверен, что это та же проблема), но в моем случае добавление этой строки:

<context:annotation-config/>

Решила мою проблему. Вам нужно либо <context:annotation-config/>, либо <context:component-scan/>, чтобы включить аннотацию @PostConstruct.

Ответ 4

В моем случае @PostConstruct не был вызван, потому что мой метод initialize() был статическим и также выдавал исключение. В любом случае метод игнорируется. Надеюсь, это поможет кому-то другому, совершив ту же ошибку. Это можно найти в консоли:

WARNING: JSF1044: Method '<XXX>' marked with the 'javax.annotation.PostConstruct' annotation cannot be static.  This method will be ignored.
WARNING: JSF1047: Method '<XXX>' marked with the 'javax.annotation.PostConstruct' annotation cannot declare any checked exceptions.  This method will be ignored.