web-dev-qa-db-fra.com

Pourquoi PostConstruct n'est pas appelé?

Je travaille sur une simple application Java EE.

J'ai des cours comme ça:

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);

    }
}

Donc, mon bean géré appelle cette méthode. Jusqu'à présent, aucun problème. Mais comme la méthode initialize n'est pas appelée, j'obtiens un NPE dans em.persist.

Pourquoi la méthode initialize n'est-elle pas appelée? J'exécute ceci sur le serveur Glassfish.

Cordialement.

22
Koray Tugay

Les annotations Java EE bean telles que @PostConstruct S'appliquent uniquement aux beans gérés par conteneur. Si vous appelez simplement new BlogEntryDao Vous-même, le conteneur ne va pas intercepter la création et appeler la méthode @PostConstruct.

(De plus, il vaut mieux utiliser @PersistenceContext Ou @PersistenceUnit Au lieu de récupérer manuellement la EntityManagerFactory dans votre méthode initialize(), et vous devriez créer un EntityManager pour chaque appel à addNewEntry(), car ils sont de courte durée. Ces modifications élimineraient la nécessité de initialize().)

23
chrylis -on strike-

Étant donné que cette question apparaît en premier sur Google pour "postconstruct not called", une autre raison pour laquelle une méthode @PostConstruct Pourrait ne pas être appelée en plus d'utiliser le mot clé new au lieu de mettre @PostConstruct Dans un Le haricot de printemps est si vous avez une dépendance circulaire.

Si ce bean devait dépendre d'un autre bean qui dépendait de ce bean, votre autre bean pourrait appeler addNewEntry() avant que BlogEntryDao soit initialisé, même si BlogEntryDao est une dépendance pour cet autre bean.

C'est parce que Spring ne savait pas quel bean vous vouliez charger en premier en raison de la référence circulaire. Dans ce cas, on peut supprimer la référence circulaire ou utiliser les paramètres du constructeur @AutoWired/@Value Au lieu des valeurs de membre ou des setters, ou si vous utilisez la configuration xml, vous pouvez peut-être permuter l'ordre dans lequel les beans sont définis.

14
Alexander Taylor

J'ai eu le même problème dans ma candidature. Vous n'avez pas posté votre fichier xml de configuration de contexte de bean (donc je ne suis pas sûr que ce soit le même problème) mais dans mon cas, j'ajoute cette ligne:

<context:annotation-config/>

Résolu mon problème. Vous avez besoin de <context:annotation-config/> ou <context:component-scan/> pour activer l'annotation @PostConstruct.

12
Tomasz Kubiak

Dans mon cas, @PostConstruct n'a pas été appelé car ma méthode initialize () était statique et lançait également une exception. Dans les deux cas, la méthode est ignorée. J'espère que cela aide quelqu'un d'autre qui a fait la même erreur. Cela peut être trouvé dans la console:

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.
3
divaylo