Search code examples
ejb-2.xjboss-4.2.x

EJB 2.x transaction isolation on JBoss 4.x


We have a legacy application which is running on a JBoss 3.x instance and which can't be changed or rewritten in large. Since the following problem might occur in several locations I'll give a somewhat abstract example, so if you need more information don't hesitate to ask and I'll try to gather it.

The main problem is the following: While the application runs fine on JBoss 3.x we want to migrate it to JBoss 4.x in order to enable a slow transition to technologies like EJB 3.x or JPA. I know that JBoss 4.x has long exceeded its end of life but unfortunately there's no way around that situation (other than keep running on 3.x).

During our tests we had the situation that uncommitted data could be read by a query in the same transaction while uncommitted relations could not.

Here's some abstract code of what the system looks like:

Entity (XML is created via xdoclet which I left out for simplicity reasons. If the settings are necessary, I can add them):

public abstract class Foo extends EntityBean, ...
{
  ...

  public abstract RelationshipLocal getRelationship(  );

  public abstract void setRelationship( RelationshipLocal relationshipEntity );


  public StammdatenAuthProcStepPK ejbCreate( RelationshipLocal relationshipEntity, ... )
     throws javax.ejb.CreateException
  {
    setComment( "some comment" );                
  }

  public void ejbPostCreate( RelationshipLocal relationshipEntity, ... )
    throws javax.ejb.CreateException
  {
    setRelationship( relationshipEntity );
  }
}

DAO method:

public Long getRelationshipUid( ... )
{ 
  Connection conn = getDataSource().getConnection();
  Statement stmt = conn.createStatement();
  ResultSet rs = stmt.executeQuery( "SELECT relationshipUid FROM foo WHERE ...;" );

  if( rs.next() )
  {
    long relationshipUid = rs.getLong( "relationshipUid" );

    if( !rs.wasNull() ) //always false, i.e. relationshipUid is always null
    {
      return new Long (relationshipUid);
    }
  }

  return null;
}

As far as I understand the system, we have the following sequence:

  • begin transaction
  • create entity ( ejbCreate() is called and an INSERT is issued )
  • update relations ( ejbPostCreate() is called and an UPDATE is issued )
  • select the relationship uid from the newly created entity using the DAO method above
  • do something with that uid (I don't know what exactly)
  • commit transaction

Since we get fields set in ejbCreate() it seems as if the transaction isolation level is set to read uncommitted, however I don't know where to check that in EJB 2.x.

In EJB 3.x I'd use EntityManager.refresh() for that and maybe a manual flush() first, but since EJB 2.x doesn't have an EntityManager that doesn't seem to be an option.

We tried to change container settings in standardjboss.xml, e.g. <commit-option> but without any success.

Any other ideas what we could look after or what could go wrong here?

Any global options (e.g. JBoss settings, no need to change the code, since we don't know all places) would be welcome.


Solution

  • We recently moved from JBOSS 4 to EAP 6. However in our JBOSS 4 configuration we have the following settings in our container configurations (standardjboss.xml):

    <container-configuration>
         <container-name>Standard CMP 2.x EntityBean post create</container-name>
         <call-logging>false</call-logging>
         <invoker-proxy-binding-name>entity-rmi-invoker</invoker-proxy-binding-name>
         <sync-on-commit-only>false</sync-on-commit-only>
         <insert-after-ejb-post-create>true</insert-after-ejb-post-create>
    ...
    <container-configuration>
    

    The changing the setting "insert-after-ejb-post-create" to true will ensure the correct database interaction so that your data will be available for a read during the same transaction.