EJB: Using EntityManager in PostConstruct Method

After building the bean, I want to get data from the database using EntityManager. This is not possible in the constructor because the EntityManager is introduced after the constructor is called. So I tried to do this in a method annotated with @PostConstruct. According to the API, after the injection is completed, the PostConstruct method is called. Query execution works, but it always returns an empty list. If I use the same query in another method, it returns the correct result. Does anyone know why this does not work in the PostConstruct method?

@Stateful(mappedName = "price") @Singleton @Startup public class PriceManagementBean implements PriceManagement { @PersistenceContext private EntityManager em; private List<PriceStep> priceSteps = Collections.synchronizedList(new ArrayList<PriceStep>()); public PriceManagementBean(){ } @PostConstruct public void init(){ javax.persistence.Query query = em.createQuery("SELECT ps FROM PriceStep ps"); List<PriceStep> res = query.getResultList(); ..... } } 
+7
source share
2 answers

Does anyone know why it doesn't work in the PostConstruct method?

Reason 1 You cannot create a bean that is @Stateful and @Singleton at the same time (well you can, but that doesn't make sense since Singletons are also Stateful), this is one of the reasons you are having problems. There are no exceptions, but there is a conflict, you need to fix it first.

Just remember:

  • A Singleton bean is a bean that maintains its state. There is only one instance of Singleton in the application, and it is distributed to all users of the application. In addition, since this is a common (perhaps better said parallel) bean, you need to implement some kind of locking mechanism using the @Lock annotation.

  • A Stateful bean is a bean that maintains every state after a transaction. When working with
    Stateful beans each user receives a copy of the bean, which will last as long as the session lasts or until the method annotated with @Remove is called

Reason 2 Even if it works, you will not be able to access the results, because you store them in an object called res, accessible only from the init () method. I suppose you would like to assign this return value to the priceSteps variable.

In any case, there is a lot of something wrong with your code for not saying everything. I don't know what your system requirements are, but here I would give you a simple solution that will allow you to access the database:

I suppose you are trying to somehow return the data to the bean life cycle because you want to avoid repeating the queries again and again if the bean is @Stateful . The fact is that you do not need to do this, you can still make your bean @Stateless and avoid the stress of your database with many queries. What you need to do is create @NamedQuery .

So annotate your PriceStep with @NamedQuery and enter the query string you wrote. In this link you will find information on how to use @NamedQueries : http://docs.oracle.com/cd/B31017_01/web.1013/b28221/ent30qry001.htm

The next thing I would like to offer you is to annotate the PriceManagementBean class as * @ Pageless . Do not worry if a new entityManager is created in each request that does not affect the database at all, since it interacts with the domain model. You don't need @PostConstruct, you just call your @NamedQuery whenever you need it, and that it. The application server will cache it and return it to each user who requires it, without interacting with the database all the time.

Here is codenipet:

 @Entity @NamedQuery( name="allPriceSteps", queryString="SELECT ps FROM PriceStep ps" ) public class PriceStep implements Serializable { ... } 

Now bean:

 @Stateless public class PriceManagementBean implements PriceManagement { @PersistenceContext private EntityManager em; public List<PriceStep> getAllPriceSteps() { Query query = em.createNamedQuery("allPriceSteps"); return query.getResultList(); } } 

Hope this is helpful. If you give more information about your system requirements, we can give you best practice tips.

+9
source

According to your requirement, please try the following

  • Delete @Stateful [CANNOT use both at the same time)

  • @Startup initializes a singleton bean during an INIT APPLICATION [Note that the application was not fully initialized]. This may cause some problem when loading the EntityManager, and I assume that the EntityManager bridge was not fully initialized. Try calling init after the application has finished running [ie], Remove @Startup

-2
source

All Articles