Re: localInstanceOfObject
Re: localInstanceOfObject
- Subject: Re: localInstanceOfObject
- From: Ramsey Gurley <email@hidden>
- Date: Tue, 21 Jul 2015 11:54:03 -0700
Hi Roger,
The error attached says:
primary key dictionary {oidProductItem = 91; oidPayment = 241; }
Which seems to indicate the ProductItemPayment is modeled with a compound PK, however the model attached indicates the OID is the PK on that table. Those two things seem to be contradicting each other.
I will hazard a guess that the flattened relationship toProductItems is causing the issue. Unless that relationship is needed for some to-many qualifier, then it may be easiest to simply remove it and create a cover method that returns the result of traversing that relationship on the entity class. Something like…
//Totally untested suggestion :-)
public NSArray<ProductItem> toProductItems() {
return (NSArray<ProductItem>)toProductItemPayments().valueForKeyPath(“toProductItem.@flatten”);
}
Assuming that removing the relation solves the issue.
On Jul 21, 2015, at 11:07 AM, Roger Perryman <email@hidden> wrote:
> Thanks Samuel. The interesting thing is that I do not have a relationship ProductItemPayment.toProductItems (with an s) in my model. I tried to reduce the image that the moderators blocked but it became unreadable so here is the textual form. ProductItemPayments is a custom class with additional attributes and relationships and a single primary key (I try to avoid compound keys except for EOGenericRecord entities).
>
> § PK » To-Many
> ƒ FK › To-One
> ø Allows Null ø Allows Null
> ◊ Class Property ¬ Locking Attribute
> ≈ Flattened Relationship
>
> ProductItem
> -----------
> § ¬ oid
> ◊ ¬ version
> ---------
> ◊ unitAmount
> ◊ unitQuantity
> ƒ ø oidInvoice
> ƒ oidProduct
> -----------
> › ◊ toProduct oidProduct -> Product.oid
> › ◊ ø toInvoice oidInvoice -> Invoice.oid
> » ◊ ø toProductItemPayments oid <- ProductItemPayment.oidProductItem
> » ◊ ≈ ø toPayments toProductItemPayments.toPayment
>
>
> ProductItemPayment
> ------------------
> § ¬ oid
> ◊ ¬ version
> ---------
> ◊ amountPledged
> ƒ ø oidPayment
> ƒ oidProductItem
> -----------
> › ◊ ø toProductItem oidProductItem -> ProductItem.oid
> › ◊ ø toPayment oidPayment -> Payment.oid
> » ◊ ø toInvoiceAudits oid <- InvoiceAudit.oidProductItem
>
>
> Payment
> -------
> § ¬ oid
> ◊ ¬ version
> ---------
> ◊ unitAmount
> -----------
> » ◊ ≈ ø toProductItems toProductItemPayments.toProductItem
> » ◊ ø toProductItemPayments oid <- ProductItemPayment.oidProductItem
>
>
>> On Jul 20, 2015, at 8:49 PM, Samuel Pelletier <email@hidden> wrote:
>>
>> Hi Roger,
>>
>> There is something strange, I may misunderstand the error but it seems the toProductItems relationship of ProductItemPayment specify a join on the oidProductItem and oidPayment columns but all your entities seems to have single column primary keys,
>>
>> I suggest to check your relationship definitions to make sure they use the corrects columns, starting with the toProductItems in ProductItemPayment.
>>
>> Samuel
>>
>>> Le 2015-07-20 à 15:39, Roger Perryman <email@hidden> a écrit :
>>>
>>> I sent this over the weekend but I didn’t notice that it was held pending approval from the list moderator. I didn’t realize there was a moderator. Apparently the message was too big due to the image I had attached showing the relevant parts of the model.
>>>
>>> I’ve done some code changes and now everything lives in the same EC. But now saveChanges() is blowing up
>>>
>>> WARN 07/19 21:28:55 (ERXNSLogLog4jBridge.java:44) - <er.extensions.appserver.ERXComponentRequestHandler>: Exception occurred while handling request:
>>> java.lang.IllegalStateException: A valid global ID could not be obtained for entity named ProductItemPayment, relationship named toProductItems, primary key dictionary {oidProductItem = 91; oidPayment = 241; }.
>>> [2015-7-19 21:28:55 EDT] <WorkerThread6> java.lang.IllegalStateException: A valid global ID could not be obtained for entity named ProductItemPayment, relationship named toProductItems, primary key dictionary {oidProductItem = 91; oidPayment = 241; }.
>>> at com.webobjects.eoaccess.EODatabaseContext.databaseOperationForIntermediateRowFromSourceObject(EODatabaseContext.java:4871)
>>> at com.webobjects.eoaccess.EODatabaseContext.recordInsertForIntermediateRowFromSourceObject(EODatabaseContext.java:4888)
>>> at com.webobjects.eoaccess.EODatabaseContext.relayAttributesInRelationshipSourceObjectDestinationObject(EODatabaseContext.java:4913)
>>> at com.webobjects.eoaccess.EODatabaseContext.relayAttributesInRelationshipSourceObjectDestinationObjects(EODatabaseContext.java:4966)
>>> at com.webobjects.eoaccess.EODatabaseContext.recordChangesInEditingContext(EODatabaseContext.java:6036)
>>> at com.webobjects.eocontrol.EOObjectStoreCoordinator.saveChangesInEditingContext(EOObjectStoreCoordinator.java:373)
>>> at com.webobjects.eocontrol.EOEditingContext.saveChanges(EOEditingContext.java:3192)
>>> at er.extensions.eof.ERXEC._saveChanges(ERXEC.java:1179)
>>> at er.extensions.eof.ERXEC.saveChanges(ERXEC.java:1102)
>>> at com.xeotech.mdspas.components.AdHocStorePayment.savePayment(AdHocStorePayment.java:255)
>>>
>>> All of the objects are in the EC
>>>
>>> EditingContext: ERXEC@12aa5705
>>> Registered [395]: List omitted
>>> Inserted [ 8]: [Invoice PK: 267], [InvoiceAudit PK: 66], [Payment PK: 241], [PaymentDetail PK: 237],
>>> [ProductItem PK: 91], [ProductItemPayment PK: 77], [ShoppingCart PK: 55],
>>> [ShoppingCartProduct PK: 54]
>>> Updated [ 3]: <Account pk:167>, <Practice pk:1>, <User pk:2>
>>>
>>> and they are assigned as I would expect
>>>
>>> Payment(6f44eaf7) :
>>> globalID = <Payment PK: 241> { pending }
>>> editingContext = ERXEC@12aa5705 Added to EC, Updated in EC
>>>
>>> Attributes
>>> comments = NULL
>>> dateRecordCreated = Sunday July 19, 2015 @ 09:25 PM *
>>> dateRecordModified = Sunday July 19, 2015 @ 09:25 PM *
>>> isActive = true *
>>> paymentNumber = FPA20150719212521850 *
>>> totalAmount = 107.0
>>> transactionDate = Sunday July 19, 2015 @ 09:25 PM
>>> version = 1 *
>>>
>>> To-One Relationships
>>> toAccount = <Account PK: 167>
>>> toAppointment = NULL
>>> toCashier = <User PK: 2> ( Patrick Abuzeni ) *
>>> toRequestType = <RequestType PK: 1> ( One Time ) *
>>> toTransactionType = NULL
>>>
>>> To-Many Relationships
>>>
>>> toPaymentDetails [ 1 ]
>>> 1) eoObj = <PaymentDetail PK: 237> ( CAC201507190BFB ) { pending }
>>>
>>> toProductItemPayments [ 1 ]
>>> 1) eoObj = <ProductItemPayment PK: 77> { pending }
>>>
>>> toProductItems [ 1 ]
>>> 1) eoObj = <ProductItem PK: 91> { pending }
>>>
>>>
>>>
>>> ProductItem(d63d22) :
>>> globalID = <ProductItem PK: 91> { pending }
>>> editingContext = ERXEC@12aa5705 Added to EC, Updated in EC
>>>
>>> Attributes
>>> dateRecordCreated = Sunday July 19, 2015 @ 09:24 PM *
>>> dateRecordModified = Sunday July 19, 2015 @ 09:24 PM *
>>> discountAmount = 0.0 *
>>> isActive = true *
>>> unitAmount = 100.0 *
>>> unitQuantity = 1 *
>>> version = 1 *
>>>
>>> To-One Relationships
>>> toAuthorizedBy = NULL
>>> toInvoice = <Invoice PK: 267> { pending }
>>> toProduct = <Product PK: 3> ( Abdominoplasty Garment ) *
>>>
>>> To-Many Relationships
>>>
>>> toPayments [ 1 ]
>>> 1) eoObj = <Payment PK: 241> { pending }
>>>
>>> toProductItemPayments [ 1 ]
>>> 1) eoObj = <ProductItemPayment PK: 77> { pending }
>>>
>>> toShoppingCartProducts [ 1 ]
>>> 1) eoObj = <ShoppingCartProduct PK: 54> { pending }
>>>
>>>
>>>
>>> ProductItemPayment(42d9e298) :
>>> globalID = <ProductItemPayment PK: 77> { pending }
>>> editingContext = ERXEC@12aa5705 Added to EC, Updated in EC
>>>
>>> Attributes
>>> amountPledged = 107.0 *
>>> datePaid = Sunday July 19, 2015 @ 09:25 PM *
>>> dateRecordCreated = Sunday July 19, 2015 @ 09:25 PM *
>>> dateRecordModified = Sunday July 19, 2015 @ 09:25 PM *
>>> isActive = true *
>>> version = 1 *
>>>
>>> To-One Relationships
>>> toPayment = <Payment PK: 241> { pending }
>>> toProductItem = <ProductItem PK: 91> { pending } *
>>>
>>> To-Many Relationships
>>>
>>> toInvoiceAudits [ 1 ]
>>> 1) eoObj = <InvoiceAudit PK: 66> { pending }
>>>
>>> Diagram of the relevant parts of the model available upon request.
>>>
>>>
>>> Any thoughts would be welcome.
>>>
>>> Roger
>>>
>>>
>>>> On Jul 16, 2015, at 4:41 PM, Roger Perryman <email@hidden> wrote:
>>>>
>>>> Thanks Aaron and Chuck for your replies. I was fairly sure (afraid?) what the answers would be. I was hoping their might be some WOnderful magical method that could be used to “pull" the objects over since that is what it looked like EOF did. I’ll check out ERXCopyable and see if that helps. I’m also looking at restructuring the code to remove the need for the extra EC and using a child EC as a backup plan.
>>>>
>>>> A few years ago when I first noticed that localInstanceOfObject returned NULL for new objects I thought it must be a bug. As I mentioned, my “fix” of just returning the original object seemed to work and I never thought much more about. It seemed to do “the right thing." I can only assume that it never encountered a toMany relationship that was new (that is the only real difference here) and the other EC was never saved so EOF didn’t notice that danger lurked. I will need to take a closer look and make sure to correct any code that needs it.
>>>>
>>>> Roger
>>>>
>>>>
>>>>> On Jul 16, 2015, at 2:20 PM, Chuck Hill <email@hidden> wrote:
>>>>>
>>>>> An EO lives in a specific EC and can’t be moved between then as a single Java object instances. The reason why localInstnace won’t work for new objects is that it does not move or copy the EO into the new EC. It creates and brand new Java EO object and loads its values from the snapshot cache (or possibly from the database but let’s not over complicate this explanation). An unsaved EO has no values in the snapshot cache (they get added when saved), so it is flat out not possible to localnstance a new object without some major changes to EOF.
>>>>>
>>>>> What might work for you is a child EC. You can then revert what changes you don’t want and save into the parent EC for final saving.
>>>>>
>>>>> ERXCopyable might also be a solution.
>>>>>
>>>>> Chuck
>>>>>
>>>>> From: <webobjects-dev-bounces+chill=email@hidden> on behalf of Aaron Rosenzweig <email@hidden>
>>>>> Date: Thursday, July 16, 2015 at 10:56 AM
>>>>> To: Roger Perryman <email@hidden>
>>>>> Cc: WebObjects Dev List <email@hidden>
>>>>> Subject: Re: localInstanceOfObject
>>>>>
>>>>> Hi Roger,
>>>>>
>>>>> I skimmed your post.
>>>>>
>>>>> You cannot local instance an unsaved object. You just cannot do it. Don’t try anything clever… the EO is tied to a unit of work (editing context) and without ever being saved it simply is not possible to local instance it.
>>>>>
>>>>> You may have to use the “memento” pattern for your particular case. Make a simple java object, nothing about DB persistence… and then make it an EO only after it has passed muster.
>>>>> AARON ROSENZWEIG / Chat 'n Bike
>>>>> e: email@hidden t: (301) 956-2319
>>>>>
>>>>>
>>>>> On Jul 16, 2015, at 1:04 PM, Roger Perryman <email@hidden> wrote:
>>>>>
>>>>>> Hi All!
>>>>>>
>>>>>> I am having an issue with local instancing an EO and I would like some help understanding the problem. I found an old thread started by Kieran Kelleher where he was having similar issues. Mike Schrag had mentioned that EOF couldn't tell if a new object localInstanced from another EC had later been saved in the other EC which could result in collisions so it erred on the side of caution. So I am probably using the method inappropriately. Hopefully someone will point out the problem and offer the correct way.
>>>>>>
>>>>>> I've noticed that when I localInstance a new EO (not yet saved to the database) both the WebObjects and WOnder versions return null for the EO. It seems odd for the method to return null if it is a new method. I wrote a customized version that detects if it is a new EO and just returns the original EO. I've been using it for quite some time now and it at least _seemed_ to work better. My use cases must have avoided conflicts.
>>>>>>
>>>>>> However, I've recently noticed problems. They may have been there before. I did recently update my computer (OSX 10.10.3) and dev environment to the latest WOnder (6.1.4-SNAPSHOT), Java 8 (1.8.0_45), Eclipse (4.4.2) with matching WOLips.
>>>>>>
>>>>>> I'm creating a new EC because many of the objects in the original EC are disposable and are not intended to be written to the DB, even if they happen to change. The problem is because of passing the original EO to the new EC instead of NULL that would normally be returned but the relationships cannot be NULL. I wrote a clone method for some of the objects for testing but it got very complex very fast because of deeper objects in the relationship. As you can see from my debugging output, all required fields (*'s) are set and relationships are set.
>>>>>>
>>>>>> This group is the objects in the old (original) EC and the original Invoice that has not been saved yet but it has had an oid assigned. It also has a to-many relationship to new ProductItem objects.
>>>>>>
>>>>>> OLD EC
>>>>>> EditingContext:ERXEC@2d334040
>>>>>> Registered [375]:List omitted
>>>>>> Inserted [ 5]:[Invoice PK: 250], [ProductItem PK: 74], [ProductItemPayment PK: 61],
>>>>>> [ShoppingCart PK: 44], [ShoppingCartProduct PK: 44]
>>>>>> Updated [ 3]:<Account pk:167>, <Practice pk:1>, <User pk:2>
>>>>>> Deleted [ 0]:EMPTY
>>>>>>
>>>>>> OLD Invoice:
>>>>>> Invoice(5bdf1c53) :
>>>>>> globalID = <Invoice PK: 250> { pending }
>>>>>> editingContext = ERXEC@2d334040 Added to EC
>>>>>>
>>>>>> Attributes
>>>>>> approvedDeposit = NULL
>>>>>> dateRecordCreated = Wednesday July 15, 2015 @ 03:19 PM *
>>>>>> dateRecordModified = Wednesday July 15, 2015 @ 03:19 PM *
>>>>>> invoiceDate = Wednesday July 15, 2015 @ 03:19 PM *
>>>>>> invoiceDiscount = NULL
>>>>>> invoiceNumber = IJD20150715151938381 *
>>>>>> isActive = true *
>>>>>> taxRate = 0.07 *
>>>>>> totalFees = 0.0 *
>>>>>> totalNonTaxable = 0.0 *
>>>>>> totalTaxable = 0.0 *
>>>>>> version = 1 *
>>>>>>
>>>>>> To-One Relationships
>>>>>> toAccount = <Account PK: 167> *
>>>>>> toCheckListPostOp = NULL
>>>>>> toCheckListPreOp = NULL
>>>>>> toCheckListSurgery = NULL
>>>>>> toCoordinator = <User PK: 2> ( Jane Doe ) *
>>>>>> toInvoiceStatus = <InvoiceStatus PK: 1> ( Open ) *
>>>>>> toInvoiceType = <InvoiceType PK: 2> ( Invoice ) *
>>>>>> toPractice = <Practice PK: 1> ( DEFAULT_PRACTICE ) *
>>>>>> toSurgeryRequest = NULL
>>>>>>
>>>>>> To-Many Relationships
>>>>>>
>>>>>> toProductItems[ 1 ]
>>>>>> 1) eoObj = <ProductItem PK: 74> { pending }
>>>>>>
>>>>>> toRequestDetails
>>>>>> No Records
>>>>>>
>>>>>> toServiceItems
>>>>>> No Records
>>>>>>
>>>>>>
>>>>>> This group is the objects in the new EC and the cloned Invoice that has not been saved yet but it has had an oid assigned. It also has a to-many relationship to new ProductItem objects. Note the oid has increased and unique attributes have been adjusted. When I try to save, it fails because the objects associated with ProductItems have a relationship in a different EC (and retain their original oids).
>>>>>>
>>>>>> NEW Invoice:
>>>>>> Invoice(6371d408) :
>>>>>> globalID = <Invoice PK: 251> { pending }
>>>>>> editingContext = ERXEC@1c741963 Added to EC, Updated in EC
>>>>>>
>>>>>> Attributes
>>>>>> approvedDeposit = NULL
>>>>>> dateRecordCreated = Wednesday July 15, 2015 @ 03:30 PM *
>>>>>> dateRecordModified = Wednesday July 15, 2015 @ 03:30 PM *
>>>>>> invoiceDate = Wednesday July 15, 2015 @ 03:19 PM *
>>>>>> invoiceDiscount = NULL
>>>>>> invoiceNumber = IJD20150715151938952 *
>>>>>> isActive = true *
>>>>>> taxRate = 0.07 *
>>>>>> totalFees = 0.0 *
>>>>>> totalNonTaxable = 0.0 *
>>>>>> totalTaxable = 0.0 *
>>>>>> version = 1 *
>>>>>>
>>>>>> To-One Relationships
>>>>>> toAccount = <Account PK: 167> *
>>>>>> toCheckListPostOp = NULL
>>>>>> toCheckListPreOp = NULL
>>>>>> toCheckListSurgery = NULL
>>>>>> toCoordinator = <User PK: 2> ( Jane Doe ) *
>>>>>> toInvoiceStatus = <InvoiceStatus PK: 1> ( Open ) *
>>>>>> toInvoiceType = <InvoiceType PK: 2> ( Invoice ) *
>>>>>> toPractice = <Practice PK: 1> ( DEFAULT_PRACTICE ) *
>>>>>> toSurgeryRequest = NULL
>>>>>>
>>>>>> To-Many Relationships
>>>>>>
>>>>>> toProductItems[ 1 ]
>>>>>> 1) eoObj = <ProductItem PK: 74> { pending }
>>>>>>
>>>>>> toRequestDetails
>>>>>> No Records
>>>>>>
>>>>>> toServiceItems
>>>>>> No Records
>>>>>>
>>>>>> NEW ProductItems:
>>>>>> (
>>>>>> ProductItem(1695d9bc) :
>>>>>> globalID = <ProductItem PK: 74> { pending }
>>>>>> editingContext = ERXEC@2d334040 Added to EC, Updated in EC
>>>>>>
>>>>>> Attributes
>>>>>> dateRecordCreated = Wednesday July 15, 2015 @ 03:15 PM *
>>>>>> dateRecordModified = Wednesday July 15, 2015 @ 03:15 PM *
>>>>>> discountAmount = 0.0 *
>>>>>> isActive = true *
>>>>>> unitAmount = 100.0 *
>>>>>> unitQuantity = 1 *
>>>>>> version = 1 *
>>>>>>
>>>>>> To-One Relationships
>>>>>> toAuthorizedBy = NULL
>>>>>> toInvoice = <Invoice PK: 250> { pending }
>>>>>> toProduct = <Product PK: 3> ( Abdominoplasty Garment ) *
>>>>>>
>>>>>> To-Many Relationships
>>>>>>
>>>>>> toGiftCards
>>>>>> No Records
>>>>>>
>>>>>> toPayments
>>>>>> No Records
>>>>>>
>>>>>> toProductItemPayments[ 1 ]
>>>>>> 1) eoObj = <ProductItemPayment PK: 61> { pending }
>>>>>>
>>>>>> toShoppingCartProducts[ 1 ]
>>>>>> 1) eoObj = <ShoppingCartProduct PK: 44> { pending }
>>>>>> )
>>>>>>
>>>>>> NEW EC
>>>>>> EditingContext:ERXEC@1c741963
>>>>>> Registered [179]:List omitted
>>>>>> Inserted [ 1]:[Invoice PK: 251]
>>>>>> Updated [ 3]:<Account pk:167>, <Practice pk:1>, <User pk:2>
>>>>>> Deleted [ 0]:EMPTY
>>>>>>
>>>>>>
>>>>>> Is there a correct way to "localInstance" an unsaved EO? Or do I need to restructure the code and perhaps use nested ECs?
>>>>>>
>>>>>> Thanks,
>>>>>>
>>>>>> Roger
>>>>>>
>>>>>> _______________________________________________
>>>>>> Do not post admin requests to the list. They will be ignored.
>>>>>> Webobjects-dev mailing list (email@hidden)
>>>>>> Help/Unsubscribe/Update your Subscription:
>>>>>>
>>>>>> This email sent to email@hidden
>>>>>
>>>>
>>>> _______________________________________________
>>>> Do not post admin requests to the list. They will be ignored.
>>>> Webobjects-dev mailing list (email@hidden)
>>>> Help/Unsubscribe/Update your Subscription:
>>>>
>>>> This email sent to email@hidden
>>>
>>>
>>> _______________________________________________
>>> Do not post admin requests to the list. They will be ignored.
>>> Webobjects-dev mailing list (email@hidden)
>>> Help/Unsubscribe/Update your Subscription:
>>>
>>> This email sent to email@hidden
>
> _______________________________________________
> Do not post admin requests to the list. They will be ignored.
> Webobjects-dev mailing list (email@hidden)
> Help/Unsubscribe/Update your Subscription:
>
> This email sent to email@hidden
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden