2013-08-10 8 views
10

Pracuję nad prostą aplikacją Java EE.Dlaczego PostConstruct nie jest wywoływany?

mam klasę tak:

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

    } 
} 

Więc moja udało fasoli nazywa ta metoda. Do tego czasu żadnych problemów. Ale ponieważ metoda initialize nie jest wywoływana, otrzymuję NPE w em.persist.

Dlaczego metoda inicjowania nie jest wywoływana? Używam tego na serwerze Glassfish.

Pozdrawiam.

+2

Na początek, nie powinno być otwarcie 'EntityManager' w zakresie globalnym; "EntityManager" z grubsza odpowiada sesji. Jeśli naprawdę potrzebujesz obsługiwać własne zarządzanie sesjami (lepiej jest wstrzykiwać @ Service ServiceCext), powinieneś tworzyć i zamykać 'EntityManager' w każdym wywołaniu' addNewEntry'. – chrylis

+1

Czy potwierdziłeś, że twój pojemnik traktuje obiekt jako coś, co wymaga zastrzyku zależności? Nie każdy obiekt jest wciągany, a jeśli po prostu wywołujesz 'new BlogEntryDao()' gdzieś, kontener może nie wiedzieć, aby zainicjować go jako komponent bean. – chrylis

+0

@chrylis Tak, dziękuję, właśnie nazywam nowy blogEntryDao. –

Odpowiedz

16

Adnotacje bean Java EE, takie jak @PostConstruct, mają zastosowanie tylko do komponentów bean zarządzanych przez kontener. Jeśli po prostu dzwonisz pod numer new BlogEntryDao, kontener nie przechwyci kreacji i nie zadzwoni pod metodę @PostConstruct.

(Ponadto, byłbyś lepiej wyłączyć za pomocą @PersistenceContext lub @PersistenceUnit zamiast ręcznego pobierania EntityManagerFactory w swojej metodzie initialize(), a powinno być stworzenie EntityManager dla każdego wywołania addNewEntry(), ponieważ są one krótkotrwałe. Making zmiany te eliminują potrzebę initialize() w ogóle).

10

Ponieważ kwestia ta pojawia się najpierw w Google „postconstruct nie nazywa się”, kolejny powód metoda @PostConstruct nie można nazwać oprócz za pomocą słowa kluczowego new zamiast umieszczać @PostConstruct w komponent Spring bean występuje w przypadku zależności cyklicznej.

Jeśli ten komponent miał być zależny od innego komponentu bean, który zależał od tego komponentu bean, inny komponent bean mógł wywołać addNewEntry() przed zainicjowaniem , mimo że parametr BlogEntryDao jest zależny od tego innego komponentu bean.

Wynikało to z tego, że Spring nie wiedział, który komponent bean chciał wczytać jako pierwszy z powodu odwołania cyklicznego. W takim przypadku można usunąć odwołanie kołowe lub użyć parametrów konstruktora zamiast wartości elementów lub ustawiaczy, lub jeśli używa się konfiguracji xml, być może można zamienić kolejność, w której zdefiniowane są fasole.

6

Miałem ten sam problem w mojej aplikacji. Nie pisać plik konfiguracyjny xml kontekstu fasoli (więc nie jestem pewien, czy to jest ten sam problem), ale w moim przypadku dodanie tej linii:

<context:annotation-config/> 

rozwiązać mój problem. Potrzebujesz albo <context:annotation-config/> lub <context:component-scan/>, aby włączyć adnotację @PostConstruct.

+0

Uwaga: jest to poprawne dla aplikacji Spring, ale pytanie dotyczyło ogólnych aplikacji JavaEE. –

1

W moim przypadku @PostConstruct nie został wywołany, ponieważ moja metoda initialize() była statyczna i również zgłaszała wyjątek. W obu przypadkach metoda jest ignorowana. Mam nadzieję, że pomoże to komuś, kto popełnił ten sam błąd. ten można znaleźć w konsoli:

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.