The problem is that during construction it is possible for the database to end up in a state that does not reflect the CMR operations done by the user. This may also lead to different application behaviour depending on the database structure in use, an unpredictability we should try to prevent.

I think there are some simple rules we can use for this.

* We allow set access to the child's CMP field during ejbCreate
  as this is needed to define the PK. Normal EJB rules prevent
  set access to that after ejbCreate completes.

* We tag the relation as being under construction. A CMR accessor
  must be used to link the parent and child at some point before
  the transaction completes. If at commit time this has not been
  done then we abort the transaction with an illegal state error.
  If the CMR access tries to link the child with a different
  parent then we also abort.

* Once the CMR accessor has been called then the parent-child
  relationship cannot be changed as this would alter the value
  of the child's primary key (which is against EJB rules even
  if the database allows it).

This supports the PK-CMR relationship used in the benchmark without violating EJB PK rules.

--
Jeremy

Dain Sundstrom wrote:
Gianny,

I don't really see an issue with allowing a developer to "implicitly" update a CMR field by modifying the CMP field mapped to the CMR field. To me it seem natural that you should be able to modify the relationship with either the CMP or CMR abstract accessor. Under the covers in the iop table, I think we could have a special accessor that takes the set on the CMP field and simply calls the CMR iop object (simple delegation). Alternatively, it could just access the same underlying data structure in tranQL, since at the bottom it is all the same cache row.

As you point out, if the CMR is part of the pk the mapped CMP field will be read only.

-dain

On Jun 14, 2005, at 6:46 AM, Matt Hogstrom wrote:

I agree with your concerns below. The code in question comes from SPECj2004 (originally SPECj2002 which was only an EJB benchmark) which was developed jointly by IBM, BEA, Oracle, Sybase, Intel, Sun, etc. There was some discussion in the OSG-Java subcommittee over this issue as some vendors interpreted the SPEC as not allowing CMP / CMR overlap. However, the implementations available at the time (already shipping and being used) allowed for the overlap and put the responsibility for using the CMP / CMR correctly. For instance, there was a protracted debate about someone breaking a relationship by setting the CMP field to a different value and breaking the relationship without the container's knowledge. Given the ambiguity in the SPEC we decided to let the current implementations be the defining standard and as a group allowed for the overlap of CMP / CMRs as well as for the manual setting of them. The Sun One AppServer recently published results using this benchmark and executes this code without error. To be consistent with the other implementations we should follow that behaviour.

It might be nice to cache the expected value in the engine and perform a verification step at transaction commit that would throw an exception if a field had been modified unexpectedly. I don't believe any of the Application Servers do that today but I'm not sure.

Would you be in favor of blindly following the defacto standard or leave this as an optional feature that provides for advanced protection?

Thanks.

Matt


----- Original Message -----
From: "Gianny Damour" <[EMAIL PROTECTED]>
To: <[email protected]>
Sent: Tuesday, June 14, 2005 7:20 AM
Subject: Re: [openejb-dev] Problem setting the PK in an entity bean with a relationship



On 14/06/2005 12:42 PM, Matt Hogstrom wrote:


I have a typical bean sequence where there is an Order and a number of Order Lines. (1 ... many) The OrderEnt is created from a Session bean coincidentally named OrderSes. The OrderEnt then in ejbPostCreate creates the appropriate OrderLines. Here is the code from OrderEnt:

   public void ejbPostCreate(OrderDataBean odb, boolean deferred)
   throws CreateException {



<snip>


Depending on the situation one of the above orderLineHome.create methods is invoked. So far, so good.

In the OrderLineEnt.create method things go a bit wrong. Here is the stack trace:

Caused by: javax.ejb.EJBException: cmp-field [orderId] is read-only.
at org.tranql.ejb.ReadOnlyCMPFieldAccessor.set (ReadOnlyCMPFieldAccessor.java:44) at org.openejb.entity.cmp.CMPSetter.invokeInstance (CMPSetter.java:74) at org.openejb.entity.cmp.CMPMethodInterceptor.intercept (CMPMethodInterceptor.java:75)



Based on this stack-trace, I confirm that the CMP field orderId is
mapped to a foreign key.


Here is the ejbCreate method that is failing

public OrderLineEntPK ejbCreate(int id, Integer orderId, String itemId, int quantity, BigDecimal totalValue, int olineStatus, java.sql.Date shipDate, BigDecimal msrp) throws CreateException {

       if( debugging )
           debug.println(3, "ejbCreate of ol_id = " + id + ",  o_id = "
                         + orderId);

       setId(id);
setOrderId(orderId); <==================== This is the line that is failing.
       setItemId(itemId);
       setQuantity(quantity);
       setTotalValue(totalValue.setScale(2, BigDecimal.ROUND_UP));
       setOlineStatus(olineStatus);



OrderId is the FK to the Order.



Fields mapped to foreign key columns are read-only. They are read- only
for the following reason:
Let's assume that:
* we have one existing line item lineItemEntity;
* lineItemEntity is already related to an order orderEntity;
* orderEntity is related to two line items, lineItemEntity (as expected)
and lineItemEntity2;
* we want to relate lineItemEntity to a new order orderEntity2;
* orderEntity2 is related to zero line items; and
* line item defines a CMR field order to set its related order.

In this specific scenario, if we set the CMR field order of
lineItemEntity to orderEntity2, then:
* orderEntity2 is now related to the line item lineItemEntity; and
* orderEntity is now related to only one line item lineItemEntity2.

In this same scenario, if we set the CMP field orderId of lineItemEntity
to the primary key of orderEntity2, then I am not sure of what the
result should be. Indeed, it is a CMP field and no specfic  semantic is
attached to it.

To some extent, I am not sure that we should allow developers to  update
relationships via a direct update to the underlying foreign key columns. We could implement a fix to have a CMR semantic for CMP fields mapped to
foreign ley columns; yet it does not sound good. Having said that,  I do
not have a strong opinion and I am happy to support such a  scenario, if
we need to.

Also, it is worth to notice that such a potential fix will only be  able
to handle CMP having simple primary keys. CMP having compound primary
keys will still have a read-only approach.


First question is the deployment right for this scenario? If it is, then I think that the container is not acting correctly. This code runs on WebLogic, Sun One, WebSphere, etc.



Do you know if they properly support such scenarii (the CMP field  must
have a CMR semantic)? Also, do you know if they do not allow such
scenarii in the case of compound PK CMP?

Thanks,
Gianny


Cheers,

- Matt











Reply via email to