[ 
https://issues.apache.org/jira/browse/OPENJPA-366?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#action_12531042
 ] 

Albert Lee commented on OPENJPA-366:
------------------------------------

After a lengthy investigation to this problem, it turns out there are a few 
problems in this application/ejb usage scenario:

1) Problem #1 - Application

The appl uses stateless session bean (SLSB) and JSE style JPA access, therefore 
the persistence context is extended. In each bean method call, the appl uses 
the persistence context to access JPA functions but did not clear the context 
upon method return. This leaves managed entities in the context propagates to 
the next client/thread who just happens to use the same session bean instance 
allocated by the EJB container from its slsb pool. 

2) Problem #2 - EJBContainer

Typically, an application server generates EJB deployment code (GenCode), 
either statically or at runtime, for an application(.ear) in order to implement 
EJB Container semantics in the application server. This generated code sits 
between the ORB/COBRA and the EJB Container. It redirects calls from the client 
to the EJB Container. Here is a brief sequence of events during this call path:

  a) ORB directs the client method call to the GenCode
  b) GenCode invokes the EJB Container to performs EJB semantics. E.g. start a 
transaction, CMP/BMP processing.  One of the function in this step is to 
allocate an user-defined bean instance.
  c) GenCode invokes the user define bean method.
  d) GenCode invokes the EJB Container to performs EJB clean up semantics. E.g. 
commit/rollback transaction, exception handling etc.  When this step is 
finished, the user-defined bean instance is returned back to the bean pool 
maintained by the EJB Container.
  e) GenCode returns the bean method returned object to ORB
   f) ORB serializes the returned object to an output stream which will be 
streamed back to the client.

In the reported problem scenario, the method being calls return a 
Vector<OrderEntity>. Everything functions normally until step d) to f). After 
step d), the SLSB instance is returned back to the EJB pool and is available 
for use by the next client while the current thread is still processing step 
f).  If the returned object contains a managed entity, the serialization 
process will eventually invocate its owning EntityManager/broker. Since step d) 
to f) are not synchronized, in a high load environment, EJB Container may 
allocate the same SLSB instance to a client in another thread. Now there are 2 
threads using managed entities in the same persistence context. Since 
EntityManager is not thread-safe (per JPA spec), the reported exception is 
observed.

3) Problem #3 - OpenJPA

OpenJPA is doing whatever it can to detect the multiple access to the same 
thread/broker. However when this happens, only a InternalException() with a 
"null" message is thrown and this percolates back to the user with an 
PersistenceException with no meaningful message to isolate the problem. This is 
a critical usability issues.


Solutions for this Jira report:

1) Application must clear all Persistence Context upon return for each bean 
method call. There are explicit example in the JPA spec demonstrates these 
usage. (JPA spec 5.7.1.1 and 5.7.1.2)
2) Proposed to enhance the error message when this error condition occurs to 
explain the cause of the problem and suggested the following possible solutions:
      a) set "openjpa.Multithreaded=true", if the application requires and 
intent to support this particular usage. Application must fully responsible for 
the behavior of this undefined semantics.
      b) request application to make sure entity manager defines as 
attribute(s) in SLSB must be cleared upon each bean method invocation.

I'll use this Jira report to addess solution 2).

Albert Lee.

> InternalException thrown in BrokerImpl.endOperation
> ---------------------------------------------------
>
>                 Key: OPENJPA-366
>                 URL: https://issues.apache.org/jira/browse/OPENJPA-366
>             Project: OpenJPA
>          Issue Type: Bug
>          Components: kernel
>    Affects Versions: 1.0.0
>         Environment: All platforms
>            Reporter: Albert Lee
>            Assignee: Albert Lee
>             Fix For: 1.0.1, 1.1.0
>
>
> Under heavy load during stress test, the following exception is observed:
> <openjpa-1.0.0-SNAPSHOT-r420667:570288M fatal general error> 
> org.apache.openjpa.persistence.PersistenceException: null
>         at 
> org.apache.openjpa.kernel.BrokerImpl.endOperation(BrokerImpl.java:1728)
>         at org.apache.openjpa.kernel.BrokerImpl.isActive(BrokerImpl.java:1676)
>         at 
> org.apache.openjpa.kernel.DelegatingBroker.isActive(DelegatingBroker.java:420)
>         at 
> org.apache.openjpa.persistence.EntityManagerImpl.isActive(EntityManagerImpl.java:502)
>         at 
> org.apache.openjpa.persistence.PersistenceExceptions$2.translate(PersistenceExceptions.java:66)
>         at 
> org.apache.openjpa.kernel.DelegatingBroker.translate(DelegatingBroker.java:110)
>         at 
> org.apache.openjpa.kernel.DelegatingBroker.newObjectId(DelegatingBroker.java:262)
>         at 
> org.apache.openjpa.persistence.EntityManagerImpl.find(EntityManagerImpl.java:347)
>         at 
> com.ibm.svt.shoppingcartModule.stationstore.StationStoreSessionBean.getListOrders(StationStoreSessionBean.java:603)
>         at 
> com.ibm.svt.shoppingcartModule.stationstore.EJSRemoteStatelessStationStoreSession_5a5c538c.getListOrders(Unknown
>  Source)
>         at 
> com.ibm.svt.shoppingcartModule.stationstore._EJSRemoteStatelessStationStoreSession_5a5c538c_Tie.getListOrders(_EJSRemoteStatelessStationStoreSession_5a5c538c_Tie.java:244)
>         at 
> com.ibm.svt.shoppingcartModule.stationstore._EJSRemoteStatelessStationStoreSession_5a5c538c_Tie._invoke(_EJSRemoteStatelessStationStoreSession_5a5c538c_Tie.java:100)
>         at 
> com.ibm.CORBA.iiop.ServerDelegate.dispatchInvokeHandler(ServerDelegate.java:613)
>         at com.ibm.CORBA.iiop.ServerDelegate.dispatch(ServerDelegate.java:466)
>         at com.ibm.rmi.iiop.ORB.process(ORB.java:503)
>         at com.ibm.CORBA.iiop.ORB.process(ORB.java:1553)
>         at com.ibm.rmi.iiop.Connection.respondTo(Connection.java:2680)
>         at com.ibm.rmi.iiop.Connection.doWork(Connection.java:2554)
>         at com.ibm.rmi.iiop.WorkUnitImpl.doWork(WorkUnitImpl.java:62)
>         at com.ibm.ejs.oa.pool.PooledThread.run(ThreadPool.java:118)
>         at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1469)
> [8/31/07 22:45:26:265 EDT] 000000c1 SystemOut     O   MDD Translating 
> exception: <openjpa-0.0.0-r420667:570288 fatal internal error> 
> org.apache.openjpa.util.InternalException: null
> [8/31/07 22:45:26:265 EDT] 000000c1 SystemErr     R   
> <openjpa-0.0.0-r420667:570288 fatal internal error> 
> org.apache.openjpa.util.InternalException: null
> [8/31/07 22:45:26:265 EDT] 000000c1 SystemErr     R           at 
> org.apache.openjpa.kernel.BrokerImpl.endOperation(BrokerImpl.java:1728)
> After some investigation, it was determined that the internal exception is 
> caused by
>              if (_operationCount < 1)
>                 throw new InternalException();
> in BrokerImpl.endOperation();
> We believe the cause of the problem is a lock() method call is missing in the 
> endOperation()
>     public boolean endOperation() {
>         lock();   <<<<<  This is the missing lock() call since 
> BrokerImpl.java was created
>         try {
>             if (_operationCount == 1 && (_autoDetach & DETACH_NONTXREAD) != 0
>                 && (_flags & FLAG_ACTIVE) == 0) {
>                 detachAllInternal(null);
>             }
>             if (_operationCount < 1)
>                 throw new InternalException();
>             return _operationCount == 1;
>         } catch (OpenJPAException ke) {
>             throw ke;
>         } catch (RuntimeException re) {
>             throw new GeneralException(re);
>         } finally {
>             _operationCount--;
>             if (_operationCount == 0)
>                 _operating.clear();
>             unlock();
>         }
>     }
> Once we have done more tests and verify the fix, I'll submit a patch for this 
> problem.
> If anyone doesn't think this is the solution. please response.
> Albert Lee.

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.

Reply via email to