i wrote this to
JBoss forum first, but jaikiran advised me to post it here for some input, hopefully ; )
robert.geisler wrote:
hello everybody,
i m confronted with a problem of simultaneous using of EJB2.1 and EJB3.0 in one server application and i hope to find some help here.
preface:currently i m migrating a complex application implemented with EJB2.1 to EJB3.0. the application consists of several moduls (about 120) that are packaged as JARs in one EAR. every modul contains a few SLSBs and EntityBeans (different layers for access, logic and data).
my problem appears in the situation when the data layer of an EJB3.0 module and the data layer of an EJB2.1 module are involved in one process (one process means one transaction for one client interaction).
usecase:a client starts a process on my server application by invoking a service of module "EJB3Module". in the first step of the process an Entity (EJB3.0) of type "EJB3Entity" is created and persisted. in the second step the primary key of this Entity (column "ID") is forwarded to the service of module "EJB21Module" that creates and persists an EntityBean (EJB2.1) of type "EJB21EntityBean". The EntityBean holds an reference to the Entity in column "EJB3Entity_ID", but the foreign key is only mapped by database and isnt mapped by JPA (EJB3.0) or CMP (EJB2.1).
problem:the problem is, when the EntityBean of module "EJB3Module" gets persisted, an exception is thrown: "foreign key violation", because the value of column "EJB3Entity_ID" in table "EJB21EntityBean" is verified against column "ID" in table "EJB3Entity" and there is no such value.
i try to explain the reason of my problem. if i am wrong in some places, please let me know.
reason:in my understanding, as the Entity is created by an EntityManager, it is registered in the persistence context, but not synchronized to database, because the transaction continues (JPA specification 3.2.3). later, when the EntityBean is being created CMP tries to write the EntityBean to database (because there is no persistence context in EJB2.1) and then database complains about foreign key, because the database doesnt know the Entity yet.
solution:i successfully tried to explicitly flush the persistence context (EntityManager.flush()) to synchronize it to database after create, update and remove of an EJB3.0 Entity: the database then knows about the Entity and the EntityBean is created.
questions:- are my assumptions correct and is this the expected behaviour?
- is there a way to set FlushModeType of EntityManager to something like always?
- if not, i guess i have to call EntityManager.flush() after every JPA action until i finally migrated all EJBs from EJB2.1 to EJB3.0. right?
- does it make sence to flush after every JPA action? or does it make even more sence to flush just before an EJB2.1 needs to read an EJB3.0 Entity?
i hope to have a discussion about my issue. please give me some input, hints and ideas, i m waiting for your answers.
regards
robert
robert.geisler wrote:
hello again...
we now decided to call EntityManager.flush() after every create, update and remove of any EJB 3.0 Entity until migration is completed.
of course it would be more accurate to flush the PersistenceContext when its really needed -because of performance costs of database work-, but we have to pay that price, because our application is too complex to find out where it is really needed -in terms of low costs ; )
i will update you know if there are some more investigations on this.
regards
robert
robert.geisler wrote:
some update here...
we are almost done with our ejb2.1-to-ejb3.0-migration. but some weeks ago we have been in deep doo-doo(?). the problem was the performance of the ejb3 entity manager when it came to persist, update and remove very, very much entities in one long transaction (long >= 2 minutes).
we tried to log and debug the data layer and finally recognized, that performance of calling entity manager's cud methods (create, update, delete) slows down more and more the longer the transaction is running.
our sample transaction took about 8 minutes before ejb 3.0. after migration, it always met the transaction timeout (>= 30 minutes (for testing)!!) and we had no idea what could be the reason. question: Hibernate? well, we tried another persistence provider (thanks JBoss for easy changing the persistence provider! :) *noirony*), EclipseLink, and got it done in about 10 minutes. answer: Hibernate!?
kind of strange behaviour, we thought, but we were able to find a solution: we now dont call flush after single cud methods, but call flush and clear on entity manager just before our data layer returns. that improved our performance extremly; after applying the new pattern, our sample transaction took about 2 minutes (Hibernate! EclipseLink now needs about 22 minutes ;)).
so far...
i hope, our experiments and experience may help others, too.
regards
robert
maybe there is not need for input... but information should not do damage anyway : )