Hi,

I've been trying to resolve an unpleasant problem for a few days now. I'm 
trying to save a graph of new and changed objects related to each other, using 
a PostgreSQL 9.5 database. The number of objects is in the range between 10 and 
100 usually. Several objects of the same class each, and numerous relationships 
involved. The model as a whole contains a few indirect cyclic relationships, 
but in these failing inserts, there aren't any cyclic relations involved.

I get something like this:

org.apache.cayenne.CayenneRuntimeException: [v.4.0.B2-SNAPSHOT Jul 12 2017 
08:27:18] Commit Exception
        at 
org.apache.cayenne.access.DataContext.flushToParent(DataContext.java:774)
        at 
org.apache.cayenne.access.DataContext.commitChangesToParent(DataContext.java:682)
        at 
com.selbstdenker.canusa.powerd.PDObjectContext.saveChanges(PDObjectContext.java:171)
        (stuff ommitted)
Caused by: org.postgresql.util.PSQLException: ERROR: duplicate key value 
violates unique constraint "pdcjourneyelementtexts_pk"
  Detail: Key (journeyelementtextskey)=(1528690) already exists.
        at 
org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2198)
        at 
org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1927)
        at 
org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:405)
        at 
org.postgresql.jdbc2.AbstractJdbc2Statement.executeBatch(AbstractJdbc2Statement.java:2892)
        at 
com.zaxxer.hikari.pool.ProxyStatement.executeBatch(ProxyStatement.java:125)
        at 
com.zaxxer.hikari.pool.HikariProxyPreparedStatement.executeBatch(HikariProxyPreparedStatement.java)
        at 
org.apache.cayenne.access.jdbc.BatchAction.runAsBatch(BatchAction.java:120)
        at 
org.apache.cayenne.access.jdbc.BatchAction.performAction(BatchAction.java:85)
        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:153)
        at org.apache.cayenne.access.DataDomain.onSyncFlush(DataDomain.java:633)
        at 
org.apache.cayenne.access.DataDomain.onSyncNoFilters(DataDomain.java:603)
        at 
org.apache.cayenne.access.DataDomain$DataDomainSyncFilterChain.onSync(DataDomain.java:764)
        at 
org.apache.cayenne.commitlog.CommitLogFilter.onSync(CommitLogFilter.java:85)
        at 
org.apache.cayenne.access.DataDomain$DataDomainSyncFilterChain.onSync(DataDomain.java:764)
        at 
org.apache.cayenne.tx.TransactionFilter$1.perform(TransactionFilter.java:73)
        at 
org.apache.cayenne.tx.TransactionFilter$1.perform(TransactionFilter.java:70)
        at 
org.apache.cayenne.tx.DefaultTransactionManager.performInTransaction(DefaultTransactionManager.java:87)
        at 
org.apache.cayenne.tx.DefaultTransactionManager.performInLocalTransaction(DefaultTransactionManager.java:59)
        at 
org.apache.cayenne.tx.DefaultTransactionManager.performInTransaction(DefaultTransactionManager.java:52)
        at 
org.apache.cayenne.tx.DefaultTransactionManager.performInTransaction(DefaultTransactionManager.java:40)
        at 
org.apache.cayenne.tx.TransactionFilter.onSync(TransactionFilter.java:70)
        at 
org.apache.cayenne.access.DataDomain$DataDomainSyncFilterChain.onSync(DataDomain.java:764)
        at org.apache.cayenne.access.DataDomain.onSync(DataDomain.java:590)
        at 
org.apache.cayenne.access.DataContext.flushToParent(DataContext.java:742)
        ... 60 more

A few notes:

* Before this insert, the max primary key of this table was 1528658, last 
sequence value was 1528688.
* It happens with one of the tables involved each time, and the table this 
happens with changes randomly.
* I had all but the m:n cross tables set to database-generated pk, but also 
tried having everything Cayenne-generated (so that Cayenne would be fetching 
new sequence values before inserting, which I verified it did). Makes no 
difference.
* I verified before each test run that all sequence values are between 0 and 32 
greater than the current max primary key of the corresponding table (wrote a 
script for that).

Then I did some research and found that maybe Cayenne fails to figure out a 
proper insert ordering. So I tried using WeightedAshwoodEntitySorter with 
@SortWeight (now in cayenne-server), following this mail thread:
https://lists.apache.org/thread.html/0452cd5ca9de85f19882539710588f1b221da7627f845902ed10a7b6@1461051077@%3Cuser.cayenne.apache.org%3E
 
<https://lists.apache.org/thread.html/0452cd5ca9de85f19882539710588f1b221da7627f845902ed10a7b6@1461051077@%3Cuser.cayenne.apache.org%3E>
but with that the application won't even start up because one of the first DML 
statements already fails:

Caused by: java.lang.NullPointerException: No record for DbEntity: 
org.apache.cayenne.map.DbEntity@a92be4f[name=PDCUserLeafletLog]
        at 
org.apache.cayenne.ashwood.AshwoodEntitySorter$DbEntityComparator.compare(AshwoodEntitySorter.java:368)
        at 
org.apache.cayenne.ashwood.AshwoodEntitySorter$DbEntityComparator.compare(AshwoodEntitySorter.java:352)
        at 
org.apache.cayenne.ashwood.WeightedAshwoodEntitySorter$WeightedDbEntityComparator.compare(WeightedAshwoodEntitySorter.java:103)
        at 
org.apache.cayenne.ashwood.WeightedAshwoodEntitySorter$WeightedDbEntityComparator.compare(WeightedAshwoodEntitySorter.java:95)
        at java.util.TimSort.countRunAndMakeAscending(TimSort.java:355)
        at java.util.TimSort.sort(TimSort.java:220)
        at java.util.Arrays.sort(Arrays.java:1512)
        at java.util.ArrayList.sort(ArrayList.java:1454)
        at java.util.Collections.sort(Collections.java:175)
        at 
org.apache.cayenne.ashwood.AshwoodEntitySorter.sortDbEntities(AshwoodEntitySorter.java:182)
        at 
org.apache.cayenne.access.DataDomainInsertBucket.appendQueriesInternal(DataDomainInsertBucket.java:56)
        at 
org.apache.cayenne.access.DataDomainSyncBucket.appendQueries(DataDomainSyncBucket.java:78)
        at 
org.apache.cayenne.access.DataDomainFlushAction.preprocess(DataDomainFlushAction.java:185)
        at 
org.apache.cayenne.access.DataDomainFlushAction.flush(DataDomainFlushAction.java:143)
        at org.apache.cayenne.access.DataDomain.onSyncFlush(DataDomain.java:633)
        at 
org.apache.cayenne.access.DataDomain.onSyncNoFilters(DataDomain.java:603)
        at 
org.apache.cayenne.access.DataDomain$DataDomainSyncFilterChain.onSync(DataDomain.java:764)
        at 
org.apache.cayenne.commitlog.CommitLogFilter.onSync(CommitLogFilter.java:85)
        at 
org.apache.cayenne.access.DataDomain$DataDomainSyncFilterChain.onSync(DataDomain.java:764)
        at 
org.apache.cayenne.tx.TransactionFilter$1.perform(TransactionFilter.java:73)
        at 
org.apache.cayenne.tx.TransactionFilter$1.perform(TransactionFilter.java:70)
        at 
org.apache.cayenne.tx.DefaultTransactionManager.performInTransaction(DefaultTransactionManager.java:87)
        at 
org.apache.cayenne.tx.DefaultTransactionManager.performInLocalTransaction(DefaultTransactionManager.java:59)
        at 
org.apache.cayenne.tx.DefaultTransactionManager.performInTransaction(DefaultTransactionManager.java:52)
        at 
org.apache.cayenne.tx.DefaultTransactionManager.performInTransaction(DefaultTransactionManager.java:40)
        at 
org.apache.cayenne.tx.TransactionFilter.onSync(TransactionFilter.java:70)
        at 
org.apache.cayenne.access.DataDomain$DataDomainSyncFilterChain.onSync(DataDomain.java:764)
        at org.apache.cayenne.access.DataDomain.onSync(DataDomain.java:590)
        at 
org.apache.cayenne.access.DataContext.flushToParent(DataContext.java:742)
        ... 18 more

This again points to this mail thread: 
http://cayenne.195.n3.nabble.com/Erratic-AshwoodEntitySorter-NPE-on-Latest-Snapshot-td4027453.html#a4028225
 
<http://cayenne.195.n3.nabble.com/Erratic-AshwoodEntitySorter-NPE-on-Latest-Snapshot-td4027453.html#a4028225>
and the NPE message is actually an output of the mentioned commit that Andrus 
added at the time, but the mail thread stopped there in December.

The mentioned class PDCUserLeafletLog has @SortWeight(1000), inherited from the 
CayenneDataObject subclass that I use for everything. I assigned lower sort 
weights, starting at 1, for the main root classes that should be inserted 
first, incrementing for each relationship from there.

So at this point, I'm at a loss how to solve this. Any help is greatly 
appreciated.

Thanks
Maik

Reply via email to