Bug #87075 ClusterJ ClusterJDatastoreException.getCode() returns 0 instead of 630

Submitted: 14 Jul 2017 16:52 Modified: 17 Jul 2017 17:28
Reporter: Michael Seydel Email Updates:
Status: Verified Impact on me:
None 
Category:MySQL Cluster: Cluster/J Severity:S2 (Serious)
Version:7.5.5 OS:MacOS (10.12.5)
Assigned to: CPU Architecture:Any
Tags: ClusterJ, ClusterJDatastoreException, constraint violation, duplicate value, getclassification, getcode, getmysqlcode, getstatus, jar, java, ndb

[14 Jul 2017 16:52] Michael Seydel
Description:
The com.mysql.clusterj.ClusterJDatastoreException.getCode() method (see: https://dev.mysql.com/doc/ndbapi/en/mccj-clusterj-clusterjdatastoreexception.html#mccj-clu...) should get the code for an error, as listed at https://dev.mysql.com/doc/ndbapi/en/ndb-error-codes-single.html

However, we find that when a 630 should result, we instead see a 0. The message string still contains the error code, and we are currently checking the substring as a workaround, but it's hacky and unreliable (e.g. the string contains that number for a different reaso).

Other getCode() results appear to work, in particular we tested 159 and 121. We find that the message strings look different in the work / not work cases; log entries from local testing:

ClusterJDatastoreException getCode => 241 for message => Error in NdbJTie: returnCode -1, code 241, mysqlCode 159, status 2, classification 4, message Invalid schema object version .
ClusterJDatastoreException getCode => 0 for message => Datastore exception. Return code: -1 Error code: 630 MySQL code: 121 Status: 2 Classification: 3 Message:  NdbRecordOperationImpl for table notification_metadata 
ClusterJDatastoreException getCode => 893 for message => Error in NdbJTie: returnCode -1, code 893, mysqlCode 121, status 2, classification 3, message Constraint violation e.g. duplicate value in unique index ndb_tiledb/def/user_identification/external_user_idx$unique.

Though it sometimes works, we're extremely hesitant to consider any of this at all reliable. We're stuck between using a method that we have observed not functioning correctly, doing string manipulation, or some combination thereof.

How to repeat:
We're using NDB database and Jar versions 7.5.5 and mysql:mysql-connector-java:6.0.6 (https://mvnrepository.com/artifact/mysql/mysql-connector-java/6.0.6).

Given a simple schema like:

CREATE TABLE example_table (
    mykey INT,
    PRIMARY KEY(mykey)
) engine=ndb;

and its ClusterJ annotated interface

@PersistenceCapable(table = "example_table")
public interface IExample {
    @PrimaryKey
    @Column(name = "mykey")
    int getMyKey();

    void setMyKey(int myKey);
}

one can run the following code:

// clusterJSession setup first
final IExample example = clusterJSession.newInstance(IExample.class);

example.setMyKey(1);

clusterJSession.persist(example);
clusterJSession.persist(example); // this will cause a constraint violation when committed

try {
    clusterJSession.flush();
} catch (ClusterJDatastoreException e) {
    System.out.println(String.format("---\ncode: %s | mysqlCode: %s | status: %s | classification: %s\nMessage:\n%s\n---",
            e.getCode(), e.getMysqlCode(), e.getStatus(), e.getClassification(), e.getMessage()));
}

and find that the first four getter methods that return ints all return 0 rather than the values they should, as are visible from the getMessage() call. In particular, I got the following output:

---
code: 0 | mysqlCode: 0 | status: 0 | classification: 0
Message:
Datastore exception. Return code: -1 Error code: 630 MySQL code: 121 Status: 2 Classification: 3 Message:  NdbRecordOperationImpl for table example_table 
Datastore exception. Return code: -1 Error code: 630 MySQL code: 121 Status: 2 Classification: 3 Message:  NdbRecordOperationImpl for table example_table 

---

but expected the first line to be "code: 630 | mysqlCode: 121 | status: 2 | classification: 3".

Thrown stack trace:
Caused by: com.mysql.clusterj.ClusterJDatastoreException: Datastore exception. Return code: -1 Error code: 630 MySQL code: 121 Status: 2 Classification: 3 Message:  NdbRecordOperationImpl for table example_table 
Datastore exception. Return code: -1 Error code: 630 MySQL code: 121 Status: 2 Classification: 3 Message:  NdbRecordOperationImpl for table example_table 

	at com.mysql.clusterj.tie.ClusterTransactionImpl.performPostExecuteCallbacks(ClusterTransactionImpl.java:590)
	at com.mysql.clusterj.tie.ClusterTransactionImpl.executeNoCommit(ClusterTransactionImpl.java:207)
	at com.mysql.clusterj.core.SessionImpl.executeNoCommit(SessionImpl.java:1498)
	at com.mysql.clusterj.core.SessionImpl.executeNoCommit(SessionImpl.java:1511)
	at com.mysql.clusterj.core.SessionImpl.flush(SessionImpl.java:1424)
	at com.mysql.clusterj.core.SessionImpl.flush(SessionImpl.java:1432)
	at com.example.Example.repro(Example.java:30)
	at com.example.Example.lambda$main$0(Example.java:16)

Suggested fix:
Remove the constructors:
ClusterJDatastoreException(String msg)
ClusterJDatastoreException(String msg, Throwable cause)
ClusterJDatastoreException(Throwable cause)

and make the relevant variables final so that they cannot accidentally not be initialized.
[17 Jul 2017 17:28] MySQL Verification Team
Hi,
Thanks for the submission. Verified as described.
all best
Bogdan

Portions of this website are copyright © 2001, 2002 The PHP Group

Page generated in 0.039 sec. using MySQL 8.4.7-u6-cloud

Timestamp references displayed by the system are UTC.
Content reproduced on this site is the property of the respective copyright holders.
It is not reviewed in advance by Oracle and does not necessarily represent the opinion of Oracle or any other party.