Hello all,

I have spent the past few hours reading up on other people with similar
problems to mine. So I am familiar with what the EJB spec says (somewhat
related to the "diamond" scenario (11.7.1 of the EJB Spec)) with respect to
when a Bean is required to write its data out to persistent storage.
However, this seems to be counterintuitive and is a serious problem for
operations that manipulate multiple data sources.

The flaw is that the Container writes changes out to persistent storage
immediately for remove() (ejbRemove()) and create() (ejbCreate())
operations, however, it doesn't write changes out for other Bean business
methods until the commit() section of the transaction.

Take the following method from my Stateless SessionBean (transaction set to
Required for the SSB and for the two CMP beans that it is manipulating)

public Integer runTest(Integer creditCardID, Integer newBillingAddressID)
throws EJBException
{

  CreditCardHome cch =
(CreditCardHome)TradeIMEJBTools.getHome("blah/CreditCardHome",CreditCardHome
.class);
  MemberCompanyAddressHome mcah =
(MemberCompanyAddressHome)TradeIMEJBTools.getHome("blah/MemberCompanyAddress
Home",MemberCompanyAddressHome.class);

  try
  {
    CreditCard cc = cch.findByPrimaryKey(creditCardID);
    CreditCardRecord ccr = cc.getRecord();

    //Get the address that this credit card is currently pointing to
    MemberCompanyAddress mca = mcah.findByPrimaryKey(new
MemberCompanyAddressPK(ccr.billing_address_id));

    //Change the address to a different one
    ccr.billing_address_id = newBillingAddressID.intValue();

    //Write the changes to the bean object
    cc.setRecord(ccr);

    //Remove the old address
    mca.remove();

    return null;


  }
  catch(Exception e)
  {
    System.out.println("Error creating record!" + e);
    throw new EJBException("Failure creating records!");
  }
}

Here's what the average guy would think that this does to the DB:

BEGIN;

SELECT billing_addres_id FROM credit_card WHERE credit_card_id =
{creditCardID}

oldBillingAddressID = {previousQuery}.billing_address_id

UPDATE credit_card SET billing_address_id = {newBillingAddressID} WHERE
credit_card_id = {creditCardID}

DELETE FROM member_company_address WHERE member_company_address_id =
{oldBillingAddressID}

COMMIT;

But in fact, the order of operations are as follows:

BEGIN;

SELECT billing_addres_id FROM credit_card WHERE credit_card_id =
{creditCardID}

oldBillingAddressID = {previousQuery}.billing_address_id

DELETE FROM member_company_address WHERE member_company_address_id =
{oldBillingAddressID}

UPDATE credit_card SET billing_address_id = {newBillingAddressID} WHERE
credit_card_id = {creditCardID}

COMMIT;

This is a serious problem ... Weblogic has implemented a
"delay-updates-until-end-of-tx" parameter to add to the deployment
descriptor to allow a developer to override this behavior... Is there any
chance that the same can be done to JBOSS? Borland App Server supposedly has
something similar ... If not, does anyone have any way to work around this
problem without writing my own BMP beans and calling ejbStore() manually
after each business method to the bean? Ideally, it would be nice to also
have a parameter to add to the deployment descriptor to force an ejbLoad()
before each business method ... I understand all of the performance
implications of doing such things, this is why it seems like it needs to be
part of each beans deployment descriptor rather than a global setting for
all entity beans.

I looked at the Interceptor classes in the org.jboss.ejb.plugins directory
and feel that it is beyond my capability to actually implement a fix myself.
However, I would be happy to test any changes that are implemented and write
a section of documention on how to use the new feature.

Thanks in advance

-Dave


_______________________________________________
Jboss-development mailing list
[EMAIL PROTECTED]
http://lists.sourceforge.net/lists/listinfo/jboss-development

Reply via email to