Details
-
Bug
-
Status: Open
-
Minor
-
Resolution: Unresolved
-
4.2.B1
-
None
-
None
Description
While we are not handling dependency cycles well during commit operation ordering, in some cases Cayenne would exhibit a rather confusing behavior, preventing a user from identifying the real problem.
Here is a perfect self-contained (Docker-based) test case to reproduce: https://git.rzen.dev/rzen/cayenne-bigint-test
E1 depends on E2 which depends on E1. When run in a "failure" mode, the following warning is printed in the logs, and an unrelated error is thrown. A commit between objects creation and establishing a relationship between them fixes the issue.
Wonder if we can detect the cycles better? Ultimately Cayenne itself should create the steps to overcome the issue (maybe in 5.0), but at the minimum it should not try to use "IdGenerationMarker" as a column value, and throw a more explicit exception.
[06/Jan/2022:13:05:15,430] main WARN o.a.c.a.t.SerializableTypeFactory: Haven't found suitable ExtendedType for class 'org.apache.cayenne.access.flush.IdGenerationMarker'. Most likely you need to define a custom ExtendedType. [06/Jan/2022:13:05:15,430] main WARN o.a.c.a.t.SerializableTypeFactory: SerializableType will be used for type conversion. [06/Jan/2022:13:05:15,431] main INFO o.a.c.l.JdbcEventLogger: [bind: 1->e1_id:org.apache.cayenne.access.flush.IdGenerationMarker@9b5c8e3e, 2->text:'e2 #0'] [06/Jan/2022:13:05:15,439] main INFO o.a.c.l.JdbcEventLogger: *** error. java.sql.SQLException: Cannot convert class [B to SQL type requested due to com.mysql.cj.exceptions.WrongArgumentException - Conversion from [B to BIGINT is not supported. at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:129) at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97) at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122) at com.mysql.cj.jdbc.ClientPreparedStatement.setObject(ClientPreparedStatement.java:1684) at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.setObject(HikariProxyPreparedStatement.java) at org.apache.cayenne.access.types.ByteArrayType.setJdbcObject(ByteArrayType.java:157) at org.apache.cayenne.access.types.ByteArrayType.setJdbcObject(ByteArrayType.java:40) at org.apache.cayenne.access.types.ExtendedTypeDecorator.setJdbcObject(ExtendedTypeDecorator.java:63) at org.apache.cayenne.dba.JdbcAdapter.bindParameter(JdbcAdapter.java:566) at org.apache.cayenne.dba.mysql.MySQLAdapter.bindParameter(MySQLAdapter.java:233) at org.apache.cayenne.dba.AutoAdapter.bindParameter(AutoAdapter.java:222) at org.apache.cayenne.access.jdbc.BatchAction.bind(BatchAction.java:62) at org.apache.cayenne.access.jdbc.BatchAction.runAsIndividualQueries(BatchAction.java:194) at org.apache.cayenne.access.jdbc.BatchAction.performAction(BatchAction.java:93) at org.apache.cayenne.access.DataNodeQueryAction.runQuery(DataNodeQueryAction.java:97) at org.apache.cayenne.access.DataNode.performQueries(DataNode.java:273) at org.apache.cayenne.access.flush.DefaultDataDomainFlushAction.lambda$executeQueries$6(DefaultDataDomainFlushAction.java:177) at java.base/java.util.HashMap.forEach(HashMap.java:1337) at org.apache.cayenne.access.flush.DefaultDataDomainFlushAction.executeQueries(DefaultDataDomainFlushAction.java:176) at org.apache.cayenne.access.flush.DefaultDataDomainFlushAction.flush(DefaultDataDomainFlushAction.java:89) at org.apache.cayenne.access.DataDomain.onSyncFlush(DataDomain.java:637) at org.apache.cayenne.access.DataDomain.onSyncNoFilters(DataDomain.java:609) at org.apache.cayenne.access.DataDomain$DataDomainSyncFilterChain.onSync(DataDomain.java:835) at org.apache.cayenne.tx.TransactionFilter.lambda$onSync$0(TransactionFilter.java:61) at org.apache.cayenne.tx.DefaultTransactionManager$BaseTransactionHandler.performInTransaction(DefaultTransactionManager.java:180) at org.apache.cayenne.tx.DefaultTransactionManager$BaseTransactionHandler.performInNewTransaction(DefaultTransactionManager.java:152) at org.apache.cayenne.tx.DefaultTransactionManager$NestedTransactionHandler.handle(DefaultTransactionManager.java:95) at org.apache.cayenne.tx.DefaultTransactionManager.performInTransaction(DefaultTransactionManager.java:62) at org.apache.cayenne.tx.DefaultTransactionManager.performInTransaction(DefaultTransactionManager.java:40) at org.apache.cayenne.tx.TransactionFilter.onSync(TransactionFilter.java:61) at org.apache.cayenne.access.DataDomain$DataDomainSyncFilterChain.onSync(DataDomain.java:834) at org.apache.cayenne.access.DataDomain.onSync(DataDomain.java:596) at org.apache.cayenne.access.DataContext.flushToParent(DataContext.java:737) at org.apache.cayenne.access.DataContext.commitChanges(DataContext.java:686) at test.TestCase.runTest(TestCase.java:27)