openjpa-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Albert Lee (JIRA)" <>
Subject [jira] Commented: (OPENJPA-366) InternalException thrown in BrokerImpl.endOperation
Date Fri, 28 Sep 2007 15:28:50 GMT


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
  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 and
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
      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:
>             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:
>         at org.apache.openjpa.kernel.BrokerImpl.endOperation(
>         at org.apache.openjpa.kernel.BrokerImpl.isActive(
>         at org.apache.openjpa.kernel.DelegatingBroker.isActive(
>         at org.apache.openjpa.persistence.EntityManagerImpl.isActive(
>         at org.apache.openjpa.persistence.PersistenceExceptions$2.translate(
>         at org.apache.openjpa.kernel.DelegatingBroker.translate(
>         at org.apache.openjpa.kernel.DelegatingBroker.newObjectId(
>         at org.apache.openjpa.persistence.EntityManagerImpl.find(
>         at
>         at
>         at
>         at
>         at
>         at
>         at
>         at
>         at
>         at
>         at
>         at
>         at$
> [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(
> 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
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.

View raw message