This week's book giveaway is in the OCAJP 8 forum. We're giving away four copies of OCA Java SE 8 Programmer I Study Guide and have Edward Finegan & Robert Liguori on-line! See this thread for details.
I earler successfully tried out Toplink deployed in Tomcat from simple web application. But now, we are required to invoke it from multiple threads. This time around we are getting the below exception:
Toplink.essentials.exceptions.EntityManagerSetupException Exception Description: Attempted to deploy PersistenceUnit [PersistenceProv1] for which predeploy method eit her had not called or had failed
Toplink.essentials.exceptions.EntityManagerSetupException Exception Description: Attempted to deploy PersistenceUnit [PersistenceProv1] for which predeploy method eit her had not called or had failed [TopLink Config]: 2007.08.16 02:42:07.076--ServerSession(7654146)--The alias name for the entity class [class com.abc.apps.entity.MyTable1] is being defaulted to: MyTable1. at oracle.toplink.essentials.internal.ejb.cmp3.EntityManagerSetupImpl.deploy(EntityManagerSetupImpl.java:195) at oracle.toplink.essentials.internal.ejb.cmp3.base.EntityManagerFactoryImpl.getServerSession(EntityManagerFactoryImpl. java:84) at oracle.toplink.essentials.internal.ejb.cmp3.base.EntityManagerFactoryImpl.createEntityManagerImpl(EntityManagerFacto ryImpl.java:127) at oracle.toplink.essentials.internal.ejb.cmp3.base.EntityManagerFactoryImpl.createEntityManagerImpl(EntityManagerFacto ryImpl.java:121) at oracle.toplink.essentials.internal.ejb.cmp3.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.ja va:76) at com.abc.apps.dao.businessInterface.DataLayerUtils.getEntityManager(DataLayerUtils.java:27) at com.abc.apps.dao.businessInterface.fetchByPrimaryKey(DataLayerInterfaceImpl.j ava:93) at com.abc.apps.business.task.EntityRemoveHandler.process(EntityRemoveHandler.java:100) at com.iii.apps.tahoe.business.task.Threading.run(ThreadingWay.java:42) at java.lang.Thread.run(Thread.java:619) Caused by: Exception [TOPLINK-28013] (Oracle TopLink Essentials - 2006.7 (Build 060720)): oracle.toplink.essentials.exceptions. EntityManagerSetupException Exception Description: Attempted to deploy PersistenceUnit [PersistenceProv1] for which predeploy method eit her had not called or had failed at oracle.toplink.essentials.exceptions.EntityManagerSetupException.cannotDeployWithoutPredeploy(EntityManagerSetupExce ption.java:167) ... 10 more
Can someone please suggest what needs to be done for this. Any help is appreciated.
Can you please give us additional information regarding how you deployed the web application? Can you please give us more details on persistence.xml bundled with your web application?
We would also like to know how are you getting a reference to Persistence Unit in your servlet code.
Joined: Jul 27, 2007
Hi, I apologize for the delay in response.
The way we packaged and deployed Toplink Essentials is as below First try - without threading: We have a business layer that is a web application. Data layer (incorporates the Toplink essentials functionality) is a jar file used as a lib file for the business layer application. We have a separate jar file that contains the entities and also the META-INF/persistence.xml file. We deployed this in Tomcat server and the setup was working fine initially.
We had to make a change in the business layer like this: Based on an input file, we spawn new threads.Each of these try to access the data layer in parallel.
In this setup too, if we configure the input file to use only one Toplink operation, it works fine.
But when multiple operations are configured, results in the above exception. Also, not all the operations fail.
Although entity manager factories are thread-safe, the TopLink Essentials JPA runtime actually only partly initializes the factory when you call Persistence.createEntityManagerFactory(). It does the rest lazily when the first entity manager is created. You might be hitting a lazy init situation where the factory has not yet been initialized but multiple concurrent threads are hitting the factory. Try putting an extra couple of lines of code in the place where your factory is being created (I am assuming that place is single-threaded) that obtains an entity manager and then closes it: EntityManager em = emf.createEntityManager(); em.close();
Below was the code we were using...it initializes an entity manager for us. It is similar to the solution suggested...but just that we do not close the entity manager
All the threads call this to obtain an entity manager instance.
Also, we are not at present working with different persistence providers for different threads... but that will be our next level once we are through with the current problem. Based on your reply, we are worried that it may not be a sound approach. Please advice.
Joined: Jul 14, 2005
You should not be calling Persistence.createEntityManagerFactory in each thread. Not only is it impractical, but potentially quite expensive, since depending upon the implementation each call to create an EMF may have to do a lot of work (process the persistence.xml file, etc). TopLink optimizes this so it does not occur, but obtaining a new factory is not meant to be a lightweight operation. Rather, you should store the factory in a static and call createEntityManager in each thread. The factory is thread-safe, and you will be correctly obtaining a new EM for each thread.
BTW, obtaining the extra EM up front is not necessary. I was just trying to see if you had uncovered a bug, but I don't think you have.
Joined: Jul 27, 2007
Thanks for your suggestion.
Initially we tried it out this way because each of the threads could possibly use a different provider and they had to execute in parallel. We wanted to check if that worked initially by having different threads call this method with different provider names.
Still, we would have expected the code to work as it is. We still dont understand why this particular exception is thrown. I could have understood an out of memory kind of exception in case the operation is resource heavy.
Anyway, thanks for your suggestion. We will check by loading the different EntityManagerFactories in a map during application startup after initializing them and obtain the instances when required.
Joined: Jul 27, 2007
Just wanted to confirm that the exception is not thrown when we stored it as suggested.