I have a class Company with a one-to-many relationship to other Companies 
(parentCompany <- subCompanies). I’m able to set a Company’s parent when 
creating one, but upon update I’m getting a NullPointerException in 
DefaultQuotingStrategy.quotedName because it’s been sent a null attribute. 
Company extends the abstract class Entity; on the DB side Entity and Company 
have a one-to-one relationship, and Entity has a parentEntity reference (which 
is modeled as parentCompany). The obj-relationship parentCompany is set up with 
the target Company and path parentEntity.

The null attribute is being added in 
org.apache.cayenne.access.DataDomainUpdateBucket.updatedAttributes. The method 
is called first with the dbEntity Entity and the an updatedSnapshot containing 
parentEntity, which is what I would expect. However, after this 
updatedAttributes is called with Company and an updatedSnapshot containing 
parentEntity, so the following line

attributes.add(entityAttributes.get(name))

will return a null attribute when trying to get the name “parentEntity” off 
Company’s attributes; that attribute only exists on Entity. I’d appreciate any 
help on preventing it from trying to add invalid attributes.

I’m not sure if this is the root cause, but  
DataDomainUpdateBucket.appendQueriesInternal calls updatedAttributes based off 
the bucket’s dbEntities, which in this case are set in 
DataDomainSyncBucket.groupObjEntitiesBySpannedDbEntities; this method is only 
adding Company as a “secondary DbEntity” (as referred to in the comments) 
because Company has a flattened attribute “name" that does not exist on the 
Entity.

Here’s the stack trace:

java.lang.NullPointerException
        at 
org.apache.cayenne.dba.DefaultQuotingStrategy.quotedName(DefaultQuotingStrategy.java:62)
        at 
org.apache.cayenne.access.translator.batch.UpdateBatchTranslator.createSql(UpdateBatchTranslator.java:60)
        at 
org.apache.cayenne.access.translator.batch.DefaultBatchTranslator.ensureTranslated(DefaultBatchTranslator.java:52)
        at 
org.apache.cayenne.access.translator.batch.DefaultBatchTranslator.getSql(DefaultBatchTranslator.java:64)
        at 
org.apache.cayenne.access.jdbc.BatchAction.runAsBatch(BatchAction.java:103)
        at 
org.apache.cayenne.access.jdbc.BatchAction.performAction(BatchAction.java:90)
        at 
org.apache.cayenne.access.DataNodeQueryAction.runQuery(DataNodeQueryAction.java:97)
        at org.apache.cayenne.access.DataNode.performQueries(DataNode.java:293)
        at 
org.apache.cayenne.access.DataDomainFlushAction.runQueries(DataDomainFlushAction.java:233)
        at 
org.apache.cayenne.access.DataDomainFlushAction.flush(DataDomainFlushAction.java:154)
        at org.apache.cayenne.access.DataDomain.onSyncFlush(DataDomain.java:693)
        at org.apache.cayenne.access.DataDomain$2.transform(DataDomain.java:659)
        at 
org.apache.cayenne.access.DataDomain.runInTransaction(DataDomain.java:720)
        at 
org.apache.cayenne.access.DataDomain.onSyncNoFilters(DataDomain.java:655)
        at 
org.apache.cayenne.access.DataDomain$DataDomainSyncFilterChain.onSync(DataDomain.java:863)
        at org.apache.cayenne.access.DataDomain.onSync(DataDomain.java:636)
        at 
org.apache.cayenne.access.DataContext.flushToParent(DataContext.java:727)
        at 
org.apache.cayenne.access.DataContext.commitChanges(DataContext.java:676)

Thanks,
Doug

Reply via email to