3 Replies Latest reply on Jan 11, 2011 11:54 PM by eevictim

    Error: Detail entity cannot find or invalidate its owning entity

    eevictim
      Guys and Gals,

      Studio Edition Version 11.1.1.3.0

      I have a Master (Orders) / Detail (Order Items) relationship in which I am trying to insert a new Detail row into a new Master record (neither have been committed). The two view objects used to create the relationship are joined by a view link and are defined as a composition association.

      Master's primary key is Docnum. Detail's primary key is Docnum, Linenum. There is a foreign key via Docnum on the two view objects.

      I click a button to add a new Master (Order). It retrieves a primary key via a DBSequence and the new Master (Order) with its information is created (but not committed). I click another button to add a Detail row and receive the following error:
      Detail entity Tgrrow (Detail *me*) with row key oracle.jbo.Key[25 -7 ] cannot find or invalidate its owning entity.
      I understand that you cannot insert a detail/child in a composition association without having a master/parent. But from what I "see" (probably incorrectly!), I just inserted its owning entity by adding the Master (Order). It even states its docnum in the error message! I've read through the forums and different blogs (http://radio-weblogs.com/0118231/stories/2003/01/17/whyDoIGetTheInvalidownerexception.html), but have returned to my general ongoing state of cluelessness.

      I tried to do what the article/blog says, but I get the same error.
        public void onRowInsert(ActionEvent actionEvent)
        {
          DCBindingContainer bindings = (DCBindingContainer)getBindings();
          BindingContext bctx = bindings.getBindingContext();
          DCDataControl control = bctx.findDataControl("AppModuleDataControl");
          ApplicationModule am = (ApplicationModule ) control.getDataProvider();
      
          ViewObject lines = am.findViewObject("TgrrowView1");    
          ViewObject orders =   am.findViewObject("TgrView1");
      
          Row existingOrder = orders.getCurrentRow();
          /*
           * Then get the details iterator via the View Link attribute accessor
           */
          RowIterator linesIter = (RowIterator)existingOrder.getAttribute("TgrrowView");
          /*
           * Then use this iterator to create the new Line
           */
          Row newLine = linesIter.createRow();
        }
      I'm probably doing something obvious; I just don't see it. Can someone point out where I've gone awry?
        • 1. Re: Error: Detail entity cannot find or invalidate its owning entity
          NickH77
          I suggest that you try to do all this logic in a custom method in the Application Module - instead of directly in the backing bean - and call this custom AM method from your backing bean.

          Also double-check that the Entity Object primary key attribute has Refresh After Insert checked in the entity attributes dialog.
          • 2. Re: Error: Detail entity cannot find or invalidate its owning entity
            eevictim
            No luck. I made sure my entities had refresh after insert and did the following in my AppModuleImpl
              public void insertRow()
              {
                ViewObjectImpl vo = getTgrView1();
                Row row = vo.getCurrentRow();
                RowIterator linesIter = (RowIterator)row.getAttribute("TgrrowView");
                Row newLine = linesIter.createRow();
              }
            I receive the same error.

            The composite association (foreign key) is between TgrView.Docnum and TgrrowView.Docnum. But TgrrowView's primary key is Docnum + Linenum. Does the entity have a problem "Seeing" when the primary key differs from the foreign key?
            • 3. Re: Error: Detail entity cannot find or invalidate its owning entity
              eevictim
              Finally got it working after reading a whole bunch of articles, not fully understanding a few of them, experimenting, and then implementing what they said anyway. That's right, magic code FTW!

              Hopefully, the following description will help those who have a similar issue. Thank you to Chris Muir's blog article here: http://one-size-doesnt-fit-all.blogspot.com/2008/07/adf-bc-eovo-initial-state-post-create.html

              In my particular instance, when I inserted a master record, JDeveloper marks the record as STATUS_INITIALIZED. It's important to note that even though I was setting my primary keys with DBSequence, this was done in my EntityImpl framework class, and then set in my entity attribute as
              adf.object.seqNextVal("SEQ_TGR")
              EntityImpl class
              public Number seqNextVal(String seqName)
              {
                Number seqNextVal;
                if (seqName != null && !seqName.equals(""))
                {
                  SequenceImpl seq = new SequenceImpl(seqName, getDBTransaction());
                  seqNextVal = seq.getSequenceNumber();
                }
                else
                {
                  seqNextVal = new Number();
                }
                return seqNextVal;
              }
              Setting the primary keys this way apparently does not trigger the switch from STATUS_INITIALIZED to STATUS_NEW. Doh! When I inserted the detail record right after, JDev looked for its parent, saw that its status was not STATUS_NEW, and promptly vomited an error message all over my screen. The trick here is to insert a little work-around code in your ViewRowImpl class. I put mine in my framework extension class.
              @Override
              public void setNewRowState(byte b) {
                if (b != Row.STATUS_INITIALIZED || getNewRowState() != Row.STATUS_NEW) {
                super.setNewRowState(b);
                }
              }
              I'd check out Chris Muir's link above for the particulars.

              On another note, there's no need to get fancy with the insert code. Simply link your detail button to a CreateInsert action method pointing to the detail iterator and you're set.